Skip to content

Commit f2a454e

Browse files
vdyegitster
authored andcommitted
unpack-trees: improve performance of next_cache_entry
To find the first non-unpacked cache entry, `next_cache_entry` iterates through index, starting at `cache_bottom`. The performance of this in full indexes is helped by `cache_bottom` advancing with each invocation of `mark_ce_used` (called by `unpack_index_entry`). However, the presence of sparse directories can prevent the `cache_bottom` from advancing in a sparse index case, effectively forcing `next_cache_entry` to search from the beginning of the index each time it is called. The `cache_bottom` must be preserved for the sparse index (see 17a1bb5 (unpack-trees: preserve cache_bottom, 2021-07-14)). Therefore, to retain the benefit `cache_bottom` provides in non-sparse index cases, a separate `hint` position indicates the first position `next_cache_entry` should search, updated each execution with a new position. Signed-off-by: Victoria Dye <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 4d1cfc1 commit f2a454e

File tree

1 file changed

+17
-6
lines changed

1 file changed

+17
-6
lines changed

unpack-trees.c

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -645,17 +645,24 @@ static void mark_ce_used_same_name(struct cache_entry *ce,
645645
}
646646
}
647647

648-
static struct cache_entry *next_cache_entry(struct unpack_trees_options *o)
648+
static struct cache_entry *next_cache_entry(struct unpack_trees_options *o, int *hint)
649649
{
650650
const struct index_state *index = o->src_index;
651651
int pos = o->cache_bottom;
652652

653+
if (*hint > pos)
654+
pos = *hint;
655+
653656
while (pos < index->cache_nr) {
654657
struct cache_entry *ce = index->cache[pos];
655-
if (!(ce->ce_flags & CE_UNPACKED))
658+
if (!(ce->ce_flags & CE_UNPACKED)) {
659+
*hint = pos + 1;
656660
return ce;
661+
}
657662
pos++;
658663
}
664+
665+
*hint = pos;
659666
return NULL;
660667
}
661668

@@ -1365,12 +1372,13 @@ static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, str
13651372

13661373
/* Are we supposed to look at the index too? */
13671374
if (o->merge) {
1375+
int hint = -1;
13681376
while (1) {
13691377
int cmp;
13701378
struct cache_entry *ce;
13711379

13721380
if (o->diff_index_cached)
1373-
ce = next_cache_entry(o);
1381+
ce = next_cache_entry(o, &hint);
13741382
else
13751383
ce = find_cache_entry(info, p);
13761384

@@ -1690,7 +1698,7 @@ static int verify_absent(const struct cache_entry *,
16901698
int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options *o)
16911699
{
16921700
struct repository *repo = the_repository;
1693-
int i, ret;
1701+
int i, hint, ret;
16941702
static struct cache_entry *dfc;
16951703
struct pattern_list pl;
16961704
int free_pattern_list = 0;
@@ -1763,13 +1771,15 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
17631771
info.pathspec = o->pathspec;
17641772

17651773
if (o->prefix) {
1774+
hint = -1;
1775+
17661776
/*
17671777
* Unpack existing index entries that sort before the
17681778
* prefix the tree is spliced into. Note that o->merge
17691779
* is always true in this case.
17701780
*/
17711781
while (1) {
1772-
struct cache_entry *ce = next_cache_entry(o);
1782+
struct cache_entry *ce = next_cache_entry(o, &hint);
17731783
if (!ce)
17741784
break;
17751785
if (ce_in_traverse_path(ce, &info))
@@ -1790,8 +1800,9 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
17901800

17911801
/* Any left-over entries in the index? */
17921802
if (o->merge) {
1803+
hint = -1;
17931804
while (1) {
1794-
struct cache_entry *ce = next_cache_entry(o);
1805+
struct cache_entry *ce = next_cache_entry(o, &hint);
17951806
if (!ce)
17961807
break;
17971808
if (unpack_index_entry(ce, o) < 0)

0 commit comments

Comments
 (0)