summaryrefslogtreecommitdiff
path: root/unpack-trees.c
diff options
context:
space:
mode:
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>2018-08-18 14:41:25 (GMT)
committerJunio C Hamano <gitster@pobox.com>2018-08-18 16:47:46 (GMT)
commitf1e11c6510846321574e0ad9443843d7ba3eb758 (patch)
tree36df1345e4cdfbd82cbe7f5f26aeed9390b86f9e /unpack-trees.c
parentb4da37380b7774248086f42bcd59397a44e1ac79 (diff)
downloadgit-f1e11c6510846321574e0ad9443843d7ba3eb758.zip
git-f1e11c6510846321574e0ad9443843d7ba3eb758.tar.gz
git-f1e11c6510846321574e0ad9443843d7ba3eb758.tar.bz2
unpack-trees: reduce malloc in cache-tree walk
This is a micro optimization that probably only shines on repos with deep directory structure. Instead of allocating and freeing a new cache_entry in every iteration, we reuse the last one and only update the parts that are new each iteration. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'unpack-trees.c')
-rw-r--r--unpack-trees.c29
1 files changed, 20 insertions, 9 deletions
diff --git a/unpack-trees.c b/unpack-trees.c
index 8376663..dbef6e1 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -685,6 +685,8 @@ static int traverse_by_cache_tree(int pos, int nr_entries, int nr_names,
{
struct cache_entry *src[MAX_UNPACK_TREES + 1] = { NULL, };
struct unpack_trees_options *o = info->data;
+ struct cache_entry *tree_ce = NULL;
+ int ce_len = 0;
int i, d;
if (!o->merge)
@@ -699,30 +701,39 @@ static int traverse_by_cache_tree(int pos, int nr_entries, int nr_names,
* get here in the first place.
*/
for (i = 0; i < nr_entries; i++) {
- struct cache_entry *tree_ce;
- int len, rc;
+ int new_ce_len, len, rc;
src[0] = o->src_index->cache[pos + i];
len = ce_namelen(src[0]);
- tree_ce = xcalloc(1, cache_entry_size(len));
+ new_ce_len = cache_entry_size(len);
+
+ if (new_ce_len > ce_len) {
+ new_ce_len <<= 1;
+ tree_ce = xrealloc(tree_ce, new_ce_len);
+ memset(tree_ce, 0, new_ce_len);
+ ce_len = new_ce_len;
+
+ tree_ce->ce_flags = create_ce_flags(0);
+
+ for (d = 1; d <= nr_names; d++)
+ src[d] = tree_ce;
+ }
tree_ce->ce_mode = src[0]->ce_mode;
- tree_ce->ce_flags = create_ce_flags(0);
tree_ce->ce_namelen = len;
oidcpy(&tree_ce->oid, &src[0]->oid);
memcpy(tree_ce->name, src[0]->name, len + 1);
- for (d = 1; d <= nr_names; d++)
- src[d] = tree_ce;
-
rc = call_unpack_fn((const struct cache_entry * const *)src, o);
- free(tree_ce);
- if (rc < 0)
+ if (rc < 0) {
+ free(tree_ce);
return rc;
+ }
mark_ce_used(src[0], o);
}
+ free(tree_ce);
if (o->debug_unpack)
printf("Unpacked %d entries from %s to %s using cache-tree\n",
nr_entries,