t/perf: add perf test for ref tombstone scenarios
Add performance tests for update-ref when many tombstones are present in a reftable. The first test exercises the scenario where all refs are deleted (creating tombstones) and then re-created with the same names, which currently exhibits quadratic behavior. The second test uses a separate repository with an asymmetric variant where refs are deleted and then new, differently-named refs are created. When the tombstones sort after the new refs, every create scans all tombstones, making this case even worse than re-creating the same refs. Helped-by: Jeff King <peff@peff.net> Signed-off-by: Kristofer Karlsson <krka@spotify.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Kristofer Karlsson committed
Jul 10, 2026 at 10:36 UTC
13d8160f4922d88aa26eb2eea74cab3fa29848b8
1 file changed
+46
t/perf/p1401-ref-store-tombstones.sh
new
+46
@@ -0,0 +1,46 @@
1
+#!/bin/sh
2
+
3
+test_description="Tests performance of ref operations with many tombstones"
4
+
5
+. ./perf-lib.sh
6
+
7
+test_expect_success "setup" '
8
+ git init --ref-format=reftable repo &&
9
+ blob=$(echo foo | git -C repo hash-object -w --stdin) &&
10
+ for i in $(test_seq 8000)
11
+ do
12
+ printf "create refs/tags/tag-%d %s\n" "$i" "$blob" ||
13
+ return 1
14
+ done >repo/input &&
15
+ git -C repo update-ref --stdin <repo/input &&
16
+ git -C repo for-each-ref --format="delete %(refname)" |
17
+ git -C repo update-ref --stdin
18
+'
19
+
20
+test_perf "recreate refs after mass delete" '
21
+ git -C repo update-ref --stdin <repo/input &&
22
+ git -C repo for-each-ref --format="delete %(refname)" |
23
+ git -C repo update-ref --stdin
24
+'
25
+
26
+test_expect_success "setup asymmetric" '
27
+ git init --ref-format=reftable repo2 &&
28
+ blob=$(echo foo | git -C repo2 hash-object -w --stdin) &&
29
+ for i in $(test_seq 8000)
30
+ do
31
+ printf "create refs/tags/old-%d %s\n" "$i" "$blob" ||
32
+ return 1
33
+ done >repo2/input-old &&
34
+ sed "s/old-/new-/" <repo2/input-old >repo2/input-new &&
35
+ git -C repo2 update-ref --stdin <repo2/input-old &&
36
+ git -C repo2 for-each-ref --format="delete %(refname)" |
37
+ git -C repo2 update-ref --stdin
38
+'
39
+
40
+test_perf "create new refs after deleting differently-named refs" '
41
+ git -C repo2 update-ref --stdin <repo2/input-new &&
42
+ git -C repo2 for-each-ref --format="delete %(refname)" refs/tags/ |
43
+ git -C repo2 update-ref --stdin
44
+'
45
+
46
+test_done