-
Notifications
You must be signed in to change notification settings - Fork 108
Improve next_cache_entry cache traversal performance
#429
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -665,17 +665,24 @@ static void mark_ce_used_same_name(struct cache_entry *ce, | |
| } | ||
| } | ||
|
|
||
| static struct cache_entry *next_cache_entry(struct unpack_trees_options *o) | ||
| static struct cache_entry *next_cache_entry(struct unpack_trees_options *o, int *hint) | ||
| { | ||
| const struct index_state *index = o->src_index; | ||
| int pos = o->cache_bottom; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As we scan the index, we are also drilling down the trees, so the cache-tree extension (if available) is giving us some idea of the range of index entries corresponding to a given tree. This can be computed dynamically, too. The In general: the |
||
|
|
||
| if (*hint > pos) | ||
| pos = *hint; | ||
|
|
||
| while (pos < index->cache_nr) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry for the retroactive review comments - if it would be better to discuss on a call lmk! I see There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
In the Git codebase, you'll see a lot of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks! |
||
| struct cache_entry *ce = index->cache[pos]; | ||
| if (!(ce->ce_flags & CE_UNPACKED)) | ||
| if (!(ce->ce_flags & CE_UNPACKED)) { | ||
| *hint = pos + 1; | ||
| return ce; | ||
| } | ||
| pos++; | ||
| } | ||
|
|
||
| *hint = pos; | ||
| return NULL; | ||
| } | ||
|
|
||
|
|
@@ -1386,12 +1393,13 @@ static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, str | |
|
|
||
| /* Are we supposed to look at the index too? */ | ||
| if (o->merge) { | ||
| int hint = -1; | ||
| while (1) { | ||
| int cmp; | ||
| struct cache_entry *ce; | ||
|
|
||
| if (o->diff_index_cached) | ||
| ce = next_cache_entry(o); | ||
| ce = next_cache_entry(o, &hint); | ||
|
Comment on lines
+1396
to
+1402
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now that I look closely at your implementation, this old code had quadratic complexity! That helps me understand why having ~70,000 index entries still took 5 seconds to iterate. I suppose I was expecting |
||
| else | ||
| ce = find_cache_entry(info, p); | ||
|
|
||
|
|
@@ -1720,7 +1728,7 @@ static int verify_absent(const struct cache_entry *, | |
| int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options *o) | ||
| { | ||
| struct repository *repo = the_repository; | ||
| int i, ret; | ||
| int i, hint, ret; | ||
| static struct cache_entry *dfc; | ||
| struct pattern_list pl; | ||
| int free_pattern_list = 0; | ||
|
|
@@ -1852,13 +1860,15 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options | |
| info.pathspec = o->pathspec; | ||
|
|
||
| if (o->prefix) { | ||
| hint = -1; | ||
|
|
||
| /* | ||
| * Unpack existing index entries that sort before the | ||
| * prefix the tree is spliced into. Note that o->merge | ||
| * is always true in this case. | ||
| */ | ||
| while (1) { | ||
| struct cache_entry *ce = next_cache_entry(o); | ||
| struct cache_entry *ce = next_cache_entry(o, &hint); | ||
| if (!ce) | ||
| break; | ||
| if (ce_in_traverse_path(ce, &info)) | ||
|
|
@@ -1879,8 +1889,9 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options | |
|
|
||
| /* Any left-over entries in the index? */ | ||
| if (o->merge) { | ||
| hint = -1; | ||
| while (1) { | ||
| struct cache_entry *ce = next_cache_entry(o); | ||
| struct cache_entry *ce = next_cache_entry(o, &hint); | ||
| if (!ce) | ||
| break; | ||
| if (unpack_index_entry(ce, o) < 0) | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.