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>

Nguyễn Thái Ngọc Duy committed Aug 18, 2018 at 16:41 UTC f1e11c6510846321574e0ad9443843d7ba3eb758
1 file changed +20 -9
unpack-trees.c
+20 -9
@@ -685,6 +685,8 @@ static int traverse_by_cache_tree(int pos, int nr_entries, int nr_names,
685 {
686 struct cache_entry *src[MAX_UNPACK_TREES + 1] = { NULL, };
687 struct unpack_trees_options *o = info->data;
688 + struct cache_entry *tree_ce = NULL;
689 + int ce_len = 0;
690 int i, d;
691
692 if (!o->merge)
@@ -699,30 +701,39 @@ static int traverse_by_cache_tree(int pos, int nr_entries, int nr_names,
701 * get here in the first place.
702 */
703 for (i = 0; i < nr_entries; i++) {
702 - struct cache_entry *tree_ce;
703 - int len, rc;
704 + int new_ce_len, len, rc;
705
706 src[0] = o->src_index->cache[pos + i];
707
708 len = ce_namelen(src[0]);
708 - tree_ce = xcalloc(1, cache_entry_size(len));
709 + new_ce_len = cache_entry_size(len);
710 +
711 + if (new_ce_len > ce_len) {
712 + new_ce_len <<= 1;
713 + tree_ce = xrealloc(tree_ce, new_ce_len);
714 + memset(tree_ce, 0, new_ce_len);
715 + ce_len = new_ce_len;
716 +
717 + tree_ce->ce_flags = create_ce_flags(0);
718 +
719 + for (d = 1; d <= nr_names; d++)
720 + src[d] = tree_ce;
721 + }
722
723 tree_ce->ce_mode = src[0]->ce_mode;
711 - tree_ce->ce_flags = create_ce_flags(0);
724 tree_ce->ce_namelen = len;
725 oidcpy(&tree_ce->oid, &src[0]->oid);
726 memcpy(tree_ce->name, src[0]->name, len + 1);
727
716 - for (d = 1; d <= nr_names; d++)
717 - src[d] = tree_ce;
718 -
728 rc = call_unpack_fn((const struct cache_entry * const *)src, o);
720 - free(tree_ce);
721 - if (rc < 0)
729 + if (rc < 0) {
730 + free(tree_ce);
731 return rc;
732 + }
733
734 mark_ce_used(src[0], o);
735 }
736 + free(tree_ce);
737 if (o->debug_unpack)
738 printf("Unpacked %d entries from %s to %s using cache-tree\n",
739 nr_entries,