Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 13ebf7b

Browse files
carlosmnEdward Thomson
authored and
Edward Thomson
committed
tree: store the entries in a growable array
Take advantage of the constant size of tree-owned arrays and store them in an array instead of a pool. This still lets us free them all at once but lets the system allocator do the work of fitting them in.
1 parent 26f2cef commit 13ebf7b

File tree

2 files changed

+38
-60
lines changed

2 files changed

+38
-60
lines changed

src/tree.c

Lines changed: 36 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -85,30 +85,26 @@ int git_tree_entry_icmp(const git_tree_entry *e1, const git_tree_entry *e2)
8585
}
8686

8787
/**
88-
* Allocate either from the pool or from the system allocator
88+
* Allocate a new self-contained entry, with enough space after it to
89+
* store the filename and the id.
8990
*/
90-
static git_tree_entry *alloc_entry_base(git_pool *pool, const char *filename, size_t filename_len, const git_oid *id)
91+
static git_tree_entry *alloc_entry(const char *filename, size_t filename_len, const git_oid *id)
9192
{
9293
git_tree_entry *entry = NULL;
9394
size_t tree_len;
9495

9596
TREE_ENTRY_CHECK_NAMELEN(filename_len);
96-
tree_len = sizeof(git_tree_entry);
9797

98-
if (!pool && (GIT_ADD_SIZET_OVERFLOW(&tree_len, tree_len, filename_len) ||
99-
GIT_ADD_SIZET_OVERFLOW(&tree_len, tree_len, 1) ||
100-
GIT_ADD_SIZET_OVERFLOW(&tree_len, tree_len, GIT_OID_RAWSZ)))
98+
if (GIT_ADD_SIZET_OVERFLOW(&tree_len, sizeof(git_tree_entry), filename_len) ||
99+
GIT_ADD_SIZET_OVERFLOW(&tree_len, tree_len, 1) ||
100+
GIT_ADD_SIZET_OVERFLOW(&tree_len, tree_len, GIT_OID_RAWSZ))
101101
return NULL;
102102

103-
entry = pool ? git_pool_mallocz(pool, tree_len) :
104-
git__calloc(1, tree_len);
103+
entry = git__calloc(1, tree_len);
105104
if (!entry)
106105
return NULL;
107106

108-
if (pool) {
109-
entry->filename = filename;
110-
entry->oid = (git_oid *) id;
111-
} else {
107+
{
112108
char *filename_ptr;
113109
void *id_ptr;
114110

@@ -126,29 +122,6 @@ static git_tree_entry *alloc_entry_base(git_pool *pool, const char *filename, si
126122
return entry;
127123
}
128124

129-
/**
130-
* Allocate a tree entry, using the poolin the tree which owns
131-
* it. This is useful when reading trees, so we don't allocate a ton
132-
* of small strings but can use the pool.
133-
*/
134-
static git_tree_entry *alloc_entry_pooled(git_pool *pool, const char *filename, size_t filename_len, const git_oid *id)
135-
{
136-
git_tree_entry *entry = NULL;
137-
138-
if (!(entry = alloc_entry_base(pool, filename, filename_len, id)))
139-
return NULL;
140-
141-
entry->pooled = true;
142-
143-
return entry;
144-
}
145-
146-
static git_tree_entry *alloc_entry(const char *filename)
147-
{
148-
git_oid dummy_id = { 0 };
149-
return alloc_entry_base(NULL, filename, strlen(filename), &dummy_id);
150-
}
151-
152125
struct tree_key_search {
153126
const char *filename;
154127
uint16_t filename_len;
@@ -250,35 +223,35 @@ static int tree_key_search(
250223

251224
void git_tree_entry_free(git_tree_entry *entry)
252225
{
253-
if (entry == NULL || entry->pooled)
226+
if (entry == NULL)
254227
return;
255228

256229
git__free(entry);
257230
}
258231

259232
int git_tree_entry_dup(git_tree_entry **dest, const git_tree_entry *source)
260233
{
234+
git_tree_entry *cpy;
235+
261236
assert(source);
262237

263-
*dest = alloc_entry_base(NULL, source->filename, source->filename_len, source->oid);
264-
if (*dest == NULL)
238+
cpy = alloc_entry(source->filename, source->filename_len, source->oid);
239+
if (cpy == NULL)
265240
return -1;
266241

242+
cpy->attr = source->attr;
243+
244+
*dest = cpy;
267245
return 0;
268246
}
269247

270248
void git_tree__free(void *_tree)
271249
{
272250
git_tree *tree = _tree;
273-
size_t i;
274-
git_tree_entry *e;
275-
276-
git_vector_foreach(&tree->entries, i, e)
277-
git_tree_entry_free(e);
278251

279252
git_odb_object_free(tree->odb_obj);
280253
git_vector_free(&tree->entries);
281-
git_pool_clear(&tree->pool);
254+
git_array_clear(tree->entries_arr);
282255
git__free(tree);
283256
}
284257

@@ -450,6 +423,7 @@ static int parse_mode(unsigned int *modep, const char *buffer, const char **buff
450423

451424
int git_tree__parse(void *_tree, git_odb_object *odb_obj)
452425
{
426+
size_t i;
453427
git_tree *tree = _tree;
454428
const char *buffer;
455429
const char *buffer_end;
@@ -460,9 +434,8 @@ int git_tree__parse(void *_tree, git_odb_object *odb_obj)
460434
buffer = git_odb_object_data(tree->odb_obj);
461435
buffer_end = buffer + git_odb_object_size(tree->odb_obj);
462436

463-
git_pool_init(&tree->pool, 1);
464-
if (git_vector_init(&tree->entries, DEFAULT_TREE_SIZE, entry_sort_cmp) < 0)
465-
return -1;
437+
git_array_init_to_size(tree->entries_arr, DEFAULT_TREE_SIZE);
438+
GITERR_CHECK_ARRAY(tree->entries_arr);
466439

467440
while (buffer < buffer_end) {
468441
git_tree_entry *entry;
@@ -479,21 +452,28 @@ int git_tree__parse(void *_tree, git_odb_object *odb_obj)
479452
filename_len = nul - buffer;
480453
/** Allocate the entry and store it in the entries vector */
481454
{
482-
/* Jump to the ID just after the path */
483-
const void *oid_ptr = buffer + filename_len + 1;
484-
entry = alloc_entry_pooled(&tree->pool, buffer, filename_len, oid_ptr);
455+
entry = git_array_alloc(tree->entries_arr);
485456
GITERR_CHECK_ALLOC(entry);
486457

487-
if (git_vector_insert(&tree->entries, entry) < 0)
488-
return -1;
489-
490458
entry->attr = attr;
459+
entry->filename_len = filename_len;
460+
entry->filename = buffer;
461+
entry->oid = (git_oid *) ((char *) buffer + filename_len + 1);
491462
}
492463

493464
buffer += filename_len + 1;
494465
buffer += GIT_OID_RAWSZ;
495466
}
496467

468+
/* Add the entries to the vector here, as we may reallocate during the loop */
469+
if (git_vector_init(&tree->entries, tree->entries_arr.size, entry_sort_cmp) < 0)
470+
return -1;
471+
472+
for (i = 0; i < tree->entries_arr.size; i++) {
473+
if (git_vector_insert(&tree->entries, git_array_get(tree->entries_arr, i)) < 0)
474+
return -1;
475+
}
476+
497477
/* The tree is sorted by definition. Bad inputs give bad outputs */
498478
tree->entries.flags |= GIT_VECTOR_SORTED;
499479

@@ -529,10 +509,9 @@ static int append_entry(
529509
if (!valid_entry_name(bld->repo, filename))
530510
return tree_error("Failed to insert entry. Invalid name for a tree entry", filename);
531511

532-
entry = alloc_entry(filename);
512+
entry = alloc_entry(filename, strlen(filename), id);
533513
GITERR_CHECK_ALLOC(entry);
534514

535-
git_oid_cpy(entry->oid, id);
536515
entry->attr = (uint16_t)filemode;
537516

538517
git_strmap_insert(bld->map, entry->filename, entry, error);
@@ -776,8 +755,9 @@ int git_treebuilder_insert(
776755
pos = git_strmap_lookup_index(bld->map, filename);
777756
if (git_strmap_valid_index(bld->map, pos)) {
778757
entry = git_strmap_value_at(bld->map, pos);
758+
git_oid_cpy((git_oid *) entry->oid, id);
779759
} else {
780-
entry = alloc_entry(filename);
760+
entry = alloc_entry(filename, strlen(filename), id);
781761
GITERR_CHECK_ALLOC(entry);
782762

783763
git_strmap_insert(bld->map, entry->filename, entry, error);
@@ -789,7 +769,6 @@ int git_treebuilder_insert(
789769
}
790770
}
791771

792-
git_oid_cpy(entry->oid, id);
793772
entry->attr = filemode;
794773

795774
if (entry_out)

src/tree.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,15 @@
1717
struct git_tree_entry {
1818
uint16_t attr;
1919
uint16_t filename_len;
20-
git_oid *oid;
21-
bool pooled;
20+
const git_oid *oid;
2221
const char *filename;
2322
};
2423

2524
struct git_tree {
2625
git_object object;
2726
git_odb_object *odb_obj;
27+
git_array_t(git_tree_entry) entries_arr;
2828
git_vector entries;
29-
git_pool pool;
3029
};
3130

3231
struct git_treebuilder {

0 commit comments

Comments
 (0)