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

Skip to content

Commit be81d4d

Browse files
committed
tree: pool the entry memory allocations
These are rather small allocations, so we end up spending a non-trivial amount of time asking the OS for memory. Since these entries are tied to the lifetime of their tree, we can give the tree a pool so we speed up the allocations.
1 parent 577006e commit be81d4d

File tree

2 files changed

+33
-6
lines changed

2 files changed

+33
-6
lines changed

src/tree.c

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,30 @@ int git_tree_entry_icmp(const git_tree_entry *e1, const git_tree_entry *e2)
8181
git__strncasecmp);
8282
}
8383

84+
/**
85+
* Allocate a tree entry, borrowing the filename from the tree which
86+
* owns it. This is useful when reading trees, so we don't allocate a
87+
* ton of small strings but can use the pool.
88+
*/
89+
static git_tree_entry *alloc_entry_pooled(git_pool *pool, const char *filename)
90+
{
91+
git_tree_entry *entry = NULL;
92+
size_t filename_len = strlen(filename), tree_len;
93+
94+
if (GIT_ADD_SIZET_OVERFLOW(&tree_len, sizeof(git_tree_entry), filename_len) ||
95+
GIT_ADD_SIZET_OVERFLOW(&tree_len, tree_len, 1) ||
96+
!(entry = git_pool_malloc(pool, tree_len)))
97+
return NULL;
98+
99+
memset(entry, 0x0, sizeof(git_tree_entry));
100+
memcpy(entry->filename, filename, filename_len);
101+
entry->filename[filename_len] = 0;
102+
entry->filename_len = filename_len;
103+
entry->pooled = true;
104+
105+
return entry;
106+
}
107+
84108
static git_tree_entry *alloc_entry(const char *filename)
85109
{
86110
git_tree_entry *entry = NULL;
@@ -198,7 +222,7 @@ static int tree_key_search(
198222

199223
void git_tree_entry_free(git_tree_entry *entry)
200224
{
201-
if (entry == NULL)
225+
if (entry == NULL || entry->pooled)
202226
return;
203227

204228
git__free(entry);
@@ -233,6 +257,7 @@ void git_tree__free(void *_tree)
233257
git_tree_entry_free(e);
234258

235259
git_vector_free(&tree->entries);
260+
git_pool_clear(&tree->pool);
236261
git__free(tree);
237262
}
238263

@@ -385,6 +410,7 @@ int git_tree__parse(void *_tree, git_odb_object *odb_obj)
385410
const char *buffer = git_odb_object_data(odb_obj);
386411
const char *buffer_end = buffer + git_odb_object_size(odb_obj);
387412

413+
git_pool_init(&tree->pool, 1);
388414
if (git_vector_init(&tree->entries, DEFAULT_TREE_SIZE, entry_sort_cmp) < 0)
389415
return -1;
390416

@@ -403,13 +429,11 @@ int git_tree__parse(void *_tree, git_odb_object *odb_obj)
403429

404430
/** Allocate the entry and store it in the entries vector */
405431
{
406-
entry = alloc_entry(buffer);
432+
entry = alloc_entry_pooled(&tree->pool, buffer);
407433
GITERR_CHECK_ALLOC(entry);
408434

409-
if (git_vector_insert(&tree->entries, entry) < 0) {
410-
git__free(entry);
435+
if (git_vector_insert(&tree->entries, entry) < 0)
411436
return -1;
412-
}
413437

414438
entry->attr = attr;
415439
}

src/tree.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,20 @@
1212
#include "odb.h"
1313
#include "vector.h"
1414
#include "strmap.h"
15+
#include "pool.h"
1516

1617
struct git_tree_entry {
1718
uint16_t attr;
1819
git_oid oid;
20+
bool pooled;
1921
size_t filename_len;
20-
char filename[1];
22+
char filename[GIT_FLEX_ARRAY];
2123
};
2224

2325
struct git_tree {
2426
git_object object;
2527
git_vector entries;
28+
git_pool pool;
2629
};
2730

2831
struct git_treebuilder {

0 commit comments

Comments
 (0)