]> git.ipfire.org Git - thirdparty/git.git/commitdiff
t/perf: add perf test for ref tombstone scenarios
authorKristofer Karlsson <krka@spotify.com>
Fri, 10 Jul 2026 10:36:06 +0000 (10:36 +0000)
committerJunio C Hamano <gitster@pobox.com>
Fri, 10 Jul 2026 15:18:56 +0000 (08:18 -0700)
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>
t/perf/p1401-ref-store-tombstones.sh [new file with mode: 0755]

diff --git a/t/perf/p1401-ref-store-tombstones.sh b/t/perf/p1401-ref-store-tombstones.sh
new file mode 100755 (executable)
index 0000000..9e3d803
--- /dev/null
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+test_description="Tests performance of ref operations with many tombstones"
+
+. ./perf-lib.sh
+
+test_expect_success "setup" '
+       git init --ref-format=reftable repo &&
+       blob=$(echo foo | git -C repo hash-object -w --stdin) &&
+       for i in $(test_seq 8000)
+       do
+               printf "create refs/tags/tag-%d %s\n" "$i" "$blob" ||
+               return 1
+       done >repo/input &&
+       git -C repo update-ref --stdin <repo/input &&
+       git -C repo for-each-ref --format="delete %(refname)" |
+       git -C repo update-ref --stdin
+'
+
+test_perf "recreate refs after mass delete" '
+       git -C repo update-ref --stdin <repo/input &&
+       git -C repo for-each-ref --format="delete %(refname)" |
+       git -C repo update-ref --stdin
+'
+
+test_expect_success "setup asymmetric" '
+       git init --ref-format=reftable repo2 &&
+       blob=$(echo foo | git -C repo2 hash-object -w --stdin) &&
+       for i in $(test_seq 8000)
+       do
+               printf "create refs/tags/old-%d %s\n" "$i" "$blob" ||
+               return 1
+       done >repo2/input-old &&
+       sed "s/old-/new-/" <repo2/input-old >repo2/input-new &&
+       git -C repo2 update-ref --stdin <repo2/input-old &&
+       git -C repo2 for-each-ref --format="delete %(refname)" |
+       git -C repo2 update-ref --stdin
+'
+
+test_perf "create new refs after deleting differently-named refs" '
+       git -C repo2 update-ref --stdin <repo2/input-new &&
+       git -C repo2 for-each-ref --format="delete %(refname)" refs/tags/ |
+       git -C repo2 update-ref --stdin
+'
+
+test_done