Skip to content

Commit

Permalink
t/perf: add perf tests for for-each-ref
Browse files Browse the repository at this point in the history
Add performance tests for 'for-each-ref'. The tests exercise different
combinations of filters/formats/options, as well as the overall performance
of 'git for-each-ref | git cat-file --batch-check' to demonstrate the
performance difference vs. 'git for-each-ref --full-deref'.

All tests are run against a repository with 40k loose refs - 10k commits,
each having a unique:

- branch
- custom ref (refs/custom/special_*)
- annotated tag pointing at the commit
- annotated tag pointing at the other annotated tag (i.e., a nested tag)

After those tests are finished, the refs are packed with 'pack-refs --all'
and the same tests are rerun.

Signed-off-by: Victoria Dye <vdye@github.com>
  • Loading branch information
vdye committed Nov 6, 2023
1 parent 7a6efc9 commit 8fceca5
Showing 1 changed file with 87 additions and 0 deletions.
87 changes: 87 additions & 0 deletions t/perf/p6300-for-each-ref.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#!/bin/sh

test_description='performance of for-each-ref'
. ./perf-lib.sh

test_perf_fresh_repo

ref_count_per_type=10000
test_iteration_count=10

test_expect_success "setup" '
test_commit_bulk $(( 1 + $ref_count_per_type )) &&
# Create refs
test_seq $ref_count_per_type |
sed "s,.*,update refs/heads/branch_& HEAD~&\nupdate refs/custom/special_& HEAD~&," |
git update-ref --stdin &&
# Create annotated tags
for i in $(test_seq $ref_count_per_type)
do
# Base tags
echo "tag tag_$i" &&
echo "mark :$i" &&
echo "from HEAD~$i" &&
printf "tagger %s <%s> %s\n" \
"$GIT_COMMITTER_NAME" \
"$GIT_COMMITTER_EMAIL" \
"$GIT_COMMITTER_DATE" &&
echo "data <<EOF" &&
echo "tag $i" &&
echo "EOF" &&
# Nested tags
echo "tag nested_$i" &&
echo "from :$i" &&
printf "tagger %s <%s> %s\n" \
"$GIT_COMMITTER_NAME" \
"$GIT_COMMITTER_EMAIL" \
"$GIT_COMMITTER_DATE" &&
echo "data <<EOF" &&
echo "nested tag $i" &&
echo "EOF" || return 1
done | git fast-import
'

test_for_each_ref () {
title="for-each-ref"
if test $# -gt 0; then
title="$title ($1)"
shift
fi
args="$@"

test_perf "$title" "
for i in \$(test_seq $test_iteration_count); do
git for-each-ref $args >/dev/null
done
"
}

run_tests () {
test_for_each_ref "$1"
test_for_each_ref "$1, no sort" --no-sort
test_for_each_ref "$1, tags" refs/tags/
test_for_each_ref "$1, tags, no sort" --no-sort refs/tags/
test_for_each_ref "$1, tags, shallow deref" '--format="%(refname) %(objectname) %(*objectname)"' refs/tags/
test_for_each_ref "$1, tags, shallow deref, no sort" --no-sort '--format="%(refname) %(objectname) %(*objectname)"' refs/tags/
test_for_each_ref "$1, tags, full deref" --full-deref '--format="%(refname) %(objectname) %(*objectname)"' refs/tags/
test_for_each_ref "$1, tags, full deref, no sort" --no-sort --full-deref '--format="%(refname) %(objectname) %(*objectname)"' refs/tags/

test_perf "for-each-ref ($1, tags) + cat-file --batch-check (full deref)" "
for i in \$(test_seq $test_iteration_count); do
git for-each-ref --format='%(objectname)^{} %(refname) %(objectname)' refs/tags/ | \
git cat-file --batch-check='%(objectname) %(rest)' >/dev/null
done
"
}

run_tests "loose"

test_expect_success 'pack refs' '
git pack-refs --all
'
run_tests "packed"

test_done

0 comments on commit 8fceca5

Please sign in to comment.