Merge branch 'td/ref-filter-restore-prefix-iteration' into seen

Commands that list branches and tags (like git branch and git tag)
have been optimized to pass the namespace prefix when initializing
their ref iterator, avoiding a loose-ref scaling regression in
repositories with many unrelated loose references.

* td/ref-filter-restore-prefix-iteration:
  ref-filter: restore prefix-scoped iteration
This commit is contained in:
Junio C Hamano
2026-06-15 10:27:30 -07:00
2 changed files with 44 additions and 8 deletions

View File

@@ -3316,15 +3316,14 @@ static int do_filter_refs(struct ref_filter *filter, unsigned int type, refs_for
if (prefix) {
struct ref_iterator *iter;
struct ref_store *store = get_main_ref_store(the_repository);
iter = refs_ref_iterator_begin(get_main_ref_store(the_repository),
"", NULL, 0, 0);
if (filter->start_after)
if (filter->start_after) {
iter = refs_ref_iterator_begin(store, "", NULL, 0, 0);
ret = start_ref_iterator_after(iter, filter->start_after);
else
ret = ref_iterator_seek(iter, prefix,
REF_ITERATOR_SEEK_SET_PREFIX);
} else {
iter = refs_ref_iterator_begin(store, prefix, NULL, 0, 0);
}
if (!ret)
ret = do_for_each_ref_iterator(iter, fn, cb_data);

View File

@@ -1,6 +1,6 @@
#!/bin/sh
test_description='performance of for-each-ref'
test_description='performance of ref-filter users'
. ./perf-lib.sh
test_perf_fresh_repo
@@ -84,4 +84,41 @@ test_expect_success 'pack refs' '
'
run_tests "packed"
test_expect_success 'setup many unrelated refs' '
git init scoped &&
test_commit -C scoped --no-tag base &&
test_seq $ref_count_per_type |
sed "s,.*,update refs/custom/unrelated_& HEAD," |
git -C scoped update-ref --stdin &&
git -C scoped update-ref refs/remotes/origin/main HEAD &&
git -C scoped update-ref refs/tags/only HEAD
'
test_perf "branch (many unrelated refs)" "
(
cd scoped &&
for i in \$(test_seq $test_iteration_count); do
git branch --format='%(refname)' >/dev/null
done
)
"
test_perf "branch --remotes (many unrelated refs)" "
(
cd scoped &&
for i in \$(test_seq $test_iteration_count); do
git branch --remotes --format='%(refname)' >/dev/null
done
)
"
test_perf "tag (many unrelated refs)" "
(
cd scoped &&
for i in \$(test_seq $test_iteration_count); do
git tag --format='%(refname)' >/dev/null
done
)
"
test_done