t/perf: add perf tests for for-each-ref

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' with "%(*fieldname)" format specifiers. 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> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Victoria Dye committed Nov 14, 2023 at 19:53 UTC 294bfc24418e81dfb204d14a3c3c24af9b195179
1 file changed +87
t/perf/p6300-for-each-ref.sh new
+87
@@ -0,0 +1,87 @@
1 +#!/bin/sh
2 +
3 +test_description='performance of for-each-ref'
4 +. ./perf-lib.sh
5 +
6 +test_perf_fresh_repo
7 +
8 +ref_count_per_type=10000
9 +test_iteration_count=10
10 +
11 +test_expect_success "setup" '
12 + test_commit_bulk $(( 1 + $ref_count_per_type )) &&
13 +
14 + # Create refs
15 + test_seq $ref_count_per_type |
16 + sed "s,.*,update refs/heads/branch_& HEAD~&\nupdate refs/custom/special_& HEAD~&," |
17 + git update-ref --stdin &&
18 +
19 + # Create annotated tags
20 + for i in $(test_seq $ref_count_per_type)
21 + do
22 + # Base tags
23 + echo "tag tag_$i" &&
24 + echo "mark :$i" &&
25 + echo "from HEAD~$i" &&
26 + printf "tagger %s <%s> %s\n" \
27 + "$GIT_COMMITTER_NAME" \
28 + "$GIT_COMMITTER_EMAIL" \
29 + "$GIT_COMMITTER_DATE" &&
30 + echo "data <<EOF" &&
31 + echo "tag $i" &&
32 + echo "EOF" &&
33 +
34 + # Nested tags
35 + echo "tag nested_$i" &&
36 + echo "from :$i" &&
37 + printf "tagger %s <%s> %s\n" \
38 + "$GIT_COMMITTER_NAME" \
39 + "$GIT_COMMITTER_EMAIL" \
40 + "$GIT_COMMITTER_DATE" &&
41 + echo "data <<EOF" &&
42 + echo "nested tag $i" &&
43 + echo "EOF" || return 1
44 + done | git fast-import
45 +'
46 +
47 +test_for_each_ref () {
48 + title="for-each-ref"
49 + if test $# -gt 0; then
50 + title="$title ($1)"
51 + shift
52 + fi
53 + args="$@"
54 +
55 + test_perf "$title" "
56 + for i in \$(test_seq $test_iteration_count); do
57 + git for-each-ref $args >/dev/null
58 + done
59 + "
60 +}
61 +
62 +run_tests () {
63 + test_for_each_ref "$1"
64 + test_for_each_ref "$1, no sort" --no-sort
65 + test_for_each_ref "$1, --count=1" --count=1
66 + test_for_each_ref "$1, --count=1, no sort" --no-sort --count=1
67 + test_for_each_ref "$1, tags" refs/tags/
68 + test_for_each_ref "$1, tags, no sort" --no-sort refs/tags/
69 + test_for_each_ref "$1, tags, dereferenced" '--format="%(refname) %(objectname) %(*objectname)"' refs/tags/
70 + test_for_each_ref "$1, tags, dereferenced, no sort" --no-sort '--format="%(refname) %(objectname) %(*objectname)"' refs/tags/
71 +
72 + test_perf "for-each-ref ($1, tags) + cat-file --batch-check (dereferenced)" "
73 + for i in \$(test_seq $test_iteration_count); do
74 + git for-each-ref --format='%(objectname)^{} %(refname) %(objectname)' refs/tags/ | \
75 + git cat-file --batch-check='%(objectname) %(rest)' >/dev/null
76 + done
77 + "
78 +}
79 +
80 +run_tests "loose"
81 +
82 +test_expect_success 'pack refs' '
83 + git pack-refs --all
84 +'
85 +run_tests "packed"
86 +
87 +test_done