Skip to content

Commit 3c71d80

Browse files
tamirdgitster
authored andcommitted
ref-filter: restore prefix-scoped iteration
dabecb9 (for-each-ref: introduce a '--start-after' option, 2025-07-15) changed branch, remote-tracking branch, and tag enumeration from constructing an iterator with the namespace prefix to constructing an unscoped iterator and seeking to the prefix. The files backend constructs its loose-ref iterator with cache priming enabled. cache_ref_iterator_begin() immediately applies the construction prefix through cache_ref_iterator_set_prefix(), reading loose refs beneath it before packed refs are opened. An empty prefix therefore reads every loose ref, and a later seek cannot undo that I/O. For these single-kind filters, construct the iterator with the namespace prefix when start_after is not set. Keep the existing unscoped construction for start_after, whose seek position may differ from the namespace prefix. With 10,000 unrelated loose refs, the p6300 tests improve as follows: before after branch 2.74 s 0.11 s branch --remotes 2.81 s 0.12 s tag 3.01 s 0.11 s Link: https://lore.kernel.org/git/aGZidwwlToWThkn8@pks.im/ Link: https://lore.kernel.org/git/xmqqikjq7s16.fsf@gitster.g/ Link: https://lore.kernel.org/r/CAOLa=ZRHKNNymXGk31YgECjUmF9nZ8GsPUdQb7aKBH5DKMz7=w@mail.gmail.com Fixes: dabecb9 ("for-each-ref: introduce a '--start-after' option") Suggested-by: Karthik Nayak <karthik.188@gmail.com> Assisted-by: Codex gpt-5.5 Signed-off-by: Tamir Duberstein <tamird@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 94f0577 commit 3c71d80

2 files changed

Lines changed: 44 additions & 8 deletions

File tree

ref-filter.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3316,15 +3316,14 @@ static int do_filter_refs(struct ref_filter *filter, unsigned int type, refs_for
33163316

33173317
if (prefix) {
33183318
struct ref_iterator *iter;
3319+
struct ref_store *store = get_main_ref_store(the_repository);
33193320

3320-
iter = refs_ref_iterator_begin(get_main_ref_store(the_repository),
3321-
"", NULL, 0, 0);
3322-
3323-
if (filter->start_after)
3321+
if (filter->start_after) {
3322+
iter = refs_ref_iterator_begin(store, "", NULL, 0, 0);
33243323
ret = start_ref_iterator_after(iter, filter->start_after);
3325-
else
3326-
ret = ref_iterator_seek(iter, prefix,
3327-
REF_ITERATOR_SEEK_SET_PREFIX);
3324+
} else {
3325+
iter = refs_ref_iterator_begin(store, prefix, NULL, 0, 0);
3326+
}
33283327

33293328
if (!ret)
33303329
ret = do_for_each_ref_iterator(iter, fn, cb_data);

t/perf/p6300-for-each-ref.sh

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/bin/sh
22

3-
test_description='performance of for-each-ref'
3+
test_description='performance of ref-filter users'
44
. ./perf-lib.sh
55

66
test_perf_fresh_repo
@@ -84,4 +84,41 @@ test_expect_success 'pack refs' '
8484
'
8585
run_tests "packed"
8686

87+
test_expect_success REFFILES 'setup many unrelated loose refs' '
88+
git init scoped &&
89+
test_commit -C scoped --no-tag base &&
90+
test_seq $ref_count_per_type |
91+
sed "s,.*,update refs/custom/unrelated_& HEAD," |
92+
git -C scoped update-ref --stdin &&
93+
git -C scoped update-ref refs/remotes/origin/main HEAD &&
94+
git -C scoped update-ref refs/tags/only HEAD
95+
'
96+
97+
test_perf "branch (many unrelated loose refs)" --prereq REFFILES "
98+
(
99+
cd scoped &&
100+
for i in \$(test_seq $test_iteration_count); do
101+
git branch --format='%(refname)' >/dev/null
102+
done
103+
)
104+
"
105+
106+
test_perf "branch --remotes (many unrelated loose refs)" --prereq REFFILES "
107+
(
108+
cd scoped &&
109+
for i in \$(test_seq $test_iteration_count); do
110+
git branch --remotes --format='%(refname)' >/dev/null
111+
done
112+
)
113+
"
114+
115+
test_perf "tag (many unrelated loose refs)" --prereq REFFILES "
116+
(
117+
cd scoped &&
118+
for i in \$(test_seq $test_iteration_count); do
119+
git tag --format='%(refname)' >/dev/null
120+
done
121+
)
122+
"
123+
87124
test_done

0 commit comments

Comments
 (0)