Skip to content

Commit 836ef2b

Browse files
pcloudsgitster
authored andcommitted
unpack-trees: reuse (still valid) cache-tree from src_index
We do n-way merge by walking the source index and n trees at the same time and add merge results to a new temporary index called o->result. The merge result for any given path could be either - keep_entry(): same old index entry in o->src_index is reused - merged_entry(): either a new entry is added, or an existing one updated - deleted_entry(): one entry from o->src_index is removed For some reason [1] we keep making sure that the source index's cache-tree is still valid if used by o->result: for all those merged/deleted entries, we invalidate the same path in o->src_index, so only cache-trees covering the "keep_entry" parts remain good. Because of this, the cache-tree from o->src_index can be perfectly reused in o->result. And in fact we already rely on this logic to reuse untracked cache in edf3b90 (unpack-trees: preserve index extensions - 2017-05-08). Move the cache-tree to o->result before doing cache_tree_update() to reduce hashing cost. Since cache_tree_update() has risen up as one of the most expensive parts in unpack_trees() after the last few patches. This does help reduce unpack_trees() time significantly (on webkit.git): before after -------------------------------------------------------------------- 0.080394752 0.051258167 s: read cache .git/index 0.216010838 0.212106298 s: preload index 0.008534301 0.280521764 s: refresh index 0.251992198 0.218160442 s: traverse_trees 0.377031383 0.374948191 s: check_updates 0.372768105 0.037040114 s: cache_tree_update 1.045887251 0.672031609 s: unpack_trees 0.314983512 0.317456290 s: write index, changed mask = 2e 0.062572653 0.038382654 s: traverse_trees 0.000022544 0.000042731 s: check_updates 0.073795585 0.050930053 s: unpack_trees 0.073807557 0.051099735 s: diff-index 1.938191592 1.614241153 s: git command: git checkout - [1] I'm pretty sure the reason is an oversight in 34110cd (Make 'unpack_trees()' have a separate source and destination index - 2008-03-06). That patch aims to _not_ update the source index at all. The invalidation should have been done on o->result in that patch. But then there was no cache-tree on o->result even then so it's pointless to do so. Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent f1e11c6 commit 836ef2b

File tree

2 files changed

+3
-1
lines changed

2 files changed

+3
-1
lines changed

read-cache.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2940,6 +2940,8 @@ void move_index_extensions(struct index_state *dst, struct index_state *src)
29402940
{
29412941
dst->untracked = src->untracked;
29422942
src->untracked = NULL;
2943+
dst->cache_tree = src->cache_tree;
2944+
src->cache_tree = NULL;
29432945
}
29442946

29452947
struct cache_entry *dup_cache_entry(const struct cache_entry *ce,

unpack-trees.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1576,6 +1576,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
15761576

15771577
ret = check_updates(o) ? (-2) : 0;
15781578
if (o->dst_index) {
1579+
move_index_extensions(&o->result, o->src_index);
15791580
if (!ret) {
15801581
if (!o->result.cache_tree)
15811582
o->result.cache_tree = cache_tree();
@@ -1584,7 +1585,6 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
15841585
WRITE_TREE_SILENT |
15851586
WRITE_TREE_REPAIR);
15861587
}
1587-
move_index_extensions(&o->result, o->src_index);
15881588
discard_index(o->dst_index);
15891589
*o->dst_index = o->result;
15901590
} else {

0 commit comments

Comments
 (0)