Skip to content

Commit 6ca17b1

Browse files
pcloudsgitster
authored andcommitted
unpack-trees: cheaper index update when walking by cache-tree
With the new cache-tree, we could mostly avoid I/O (due to odb access) the code mostly becomes a loop of "check this, check that, add the entry to the index". We could skip a couple checks in this giant loop to go faster: - We know here that we're copying entries from the source index to the result one. All paths in the source index must have been validated at load time already (and we're not taking strange paths from tree objects) which means we can skip verify_path() without compromise. - We also know that D/F conflicts can't happen for all these entries (since cache-tree and all the trees are the same) so we can skip that as well. This gives rather nice speedups for "unpack trees" rows where "unpack trees" time is now cut in half compared to when traverse_by_cache_tree() is added, or 1/7 of the original "unpack trees" time. baseline cache-tree this patch -------------------------------------------------------------------- 0.018239226 0.019365414 0.020519621 s: read cache .git/index 0.052541655 0.049605548 0.048814384 s: preload index 0.001537598 0.001571695 0.001575382 s: refresh index 0.168167768 0.049677212 0.024719308 s: unpack trees 0.002897186 0.002845256 0.002805555 s: update worktree after a merge 0.131661745 0.136597522 0.134891617 s: repair cache-tree 0.075389117 0.075422517 0.074832291 s: write index, changed mask = 2a 0.111702023 0.032813253 0.008616479 s: unpack trees 0.000023245 0.000022002 0.000026630 s: update worktree after a merge 0.111793866 0.032933140 0.008714071 s: diff-index 0.587933288 0.398924370 0.380452871 s: git command: /home/pclouds/w/git/git Total saving of this new patch looks even less impressive, now that time spent in unpacking trees is so small. Which is why the next attempt should be on that "repair cache-tree" line. Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 7c6f863 commit 6ca17b1

File tree

4 files changed

+31
-1
lines changed

4 files changed

+31
-1
lines changed

cache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,7 @@ extern int index_name_pos(const struct index_state *, const char *name, int name
673673
#define ADD_CACHE_JUST_APPEND 8 /* Append only; tree.c::read_tree() */
674674
#define ADD_CACHE_NEW_ONLY 16 /* Do not replace existing ones */
675675
#define ADD_CACHE_KEEP_CACHE_TREE 32 /* Do not invalidate cache-tree */
676+
#define ADD_CACHE_SKIP_VERIFY_PATH 64 /* Do not verify path */
676677
extern int add_index_entry(struct index_state *, struct cache_entry *ce, int option);
677678
extern void rename_index_entry_at(struct index_state *, int pos, const char *new_name);
678679

read-cache.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1170,6 +1170,7 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e
11701170
int ok_to_add = option & ADD_CACHE_OK_TO_ADD;
11711171
int ok_to_replace = option & ADD_CACHE_OK_TO_REPLACE;
11721172
int skip_df_check = option & ADD_CACHE_SKIP_DFCHECK;
1173+
int skip_verify_path = option & ADD_CACHE_SKIP_VERIFY_PATH;
11731174
int new_only = option & ADD_CACHE_NEW_ONLY;
11741175

11751176
if (!(option & ADD_CACHE_KEEP_CACHE_TREE))
@@ -1210,7 +1211,7 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e
12101211

12111212
if (!ok_to_add)
12121213
return -1;
1213-
if (!verify_path(ce->name, ce->ce_mode))
1214+
if (!skip_verify_path && !verify_path(ce->name, ce->ce_mode))
12141215
return error("Invalid path '%s'", ce->name);
12151216

12161217
if (!skip_df_check &&

unpack-trees.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ static int do_add_entry(struct unpack_trees_options *o, struct cache_entry *ce,
201201

202202
ce->ce_flags = (ce->ce_flags & ~clear) | set;
203203
return add_index_entry(&o->result, ce,
204+
o->extra_add_index_flags |
204205
ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE);
205206
}
206207

@@ -701,6 +702,24 @@ static int traverse_by_cache_tree(int pos, int nr_entries, int nr_names,
701702
if (!o->merge)
702703
BUG("We need cache-tree to do this optimization");
703704

705+
/*
706+
* Try to keep add_index_entry() as fast as possible since
707+
* we're going to do a lot of them.
708+
*
709+
* Skipping verify_path() should totally be safe because these
710+
* paths are from the source index, which must have been
711+
* verified.
712+
*
713+
* Skipping D/F and cache-tree validation checks is trickier
714+
* because it assumes what n-merge code would do when all
715+
* trees and the index are the same. We probably could just
716+
* optimize those code instead (e.g. we don't invalidate that
717+
* many cache-tree, but the searching for them is very
718+
* expensive).
719+
*/
720+
o->extra_add_index_flags = ADD_CACHE_SKIP_DFCHECK;
721+
o->extra_add_index_flags |= ADD_CACHE_SKIP_VERIFY_PATH;
722+
704723
/*
705724
* Do what unpack_callback() and unpack_nondirectories() normally
706725
* do. But we walk all paths recursively in just one loop instead.
@@ -742,6 +761,7 @@ static int traverse_by_cache_tree(int pos, int nr_entries, int nr_names,
742761

743762
mark_ce_used(src[0], o);
744763
}
764+
o->extra_add_index_flags = 0;
745765
free(tree_ce);
746766
if (o->debug_unpack)
747767
printf("Unpacked %d entries from %s to %s using cache-tree\n",
@@ -1561,6 +1581,13 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
15611581
if (!ret) {
15621582
if (!o->result.cache_tree)
15631583
o->result.cache_tree = cache_tree();
1584+
/*
1585+
* TODO: Walk o.src_index->cache_tree, quickly check
1586+
* if o->result.cache has the exact same content for
1587+
* any valid cache-tree in o.src_index, then we can
1588+
* just copy the cache-tree over instead of hashing a
1589+
* new tree object.
1590+
*/
15641591
if (!cache_tree_fully_valid(o->result.cache_tree))
15651592
cache_tree_update(&o->result,
15661593
WRITE_TREE_SILENT |

unpack-trees.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ struct unpack_trees_options {
8080
struct index_state result;
8181

8282
struct exclude_list *el; /* for internal use */
83+
unsigned int extra_add_index_flags;
8384
};
8485

8586
extern int unpack_trees(unsigned n, struct tree_desc *t,

0 commit comments

Comments
 (0)