summaryrefslogtreecommitdiff
path: root/refs/files-backend.c
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2024-11-20 08:51:35 +0100
committerJunio C Hamano <gitster@pobox.com>2024-11-21 07:59:16 +0900
commite4929cdf797467b5d55a976ee938f1d4f358900e (patch)
tree8d6948f480a5e093667c8c766a3817422bd0af8e /refs/files-backend.c
parent00bd6c3e4649d3e764db7ffcfbd317aabd2525d3 (diff)
refs: skip collision checks in initial transactions
Reference transactions use `refs_verify_refname_available()` to check for colliding references. This check consists of two parts: - Checks for whether multiple ref updates in the same transaction conflict with each other. - Checks for whether existing refs conflict with any refs part of the transaction. While we generally cannot avoid the first check, the second check is superfluous in cases where the transaction is an initial one in an otherwise empty ref store. The check results in multiple ref reads as well as the creation of a ref iterator for every ref we're checking, which adds up quite fast when performing the check for many refs. Introduce a new flag that allows us to skip this check and wire it up in such that the backends pass it when running an initial transaction. This leads to significant speedups when migrating ref storage backends. From "files" to "reftable": Benchmark 1: migrate files:reftable (refcount = 100000, revision = HEAD~) Time (mean ± σ): 472.4 ms ± 6.7 ms [User: 175.9 ms, System: 285.2 ms] Range (min … max): 463.5 ms … 483.2 ms 10 runs Benchmark 2: migrate files:reftable (refcount = 100000, revision = HEAD) Time (mean ± σ): 86.1 ms ± 1.9 ms [User: 67.9 ms, System: 16.0 ms] Range (min … max): 82.9 ms … 90.9 ms 29 runs Summary migrate files:reftable (refcount = 100000, revision = HEAD) ran 5.48 ± 0.15 times faster than migrate files:reftable (refcount = 100000, revision = HEAD~) And from "reftable" to "files": Benchmark 1: migrate reftable:files (refcount = 100000, revision = HEAD~) Time (mean ± σ): 452.7 ms ± 3.4 ms [User: 209.9 ms, System: 235.4 ms] Range (min … max): 445.9 ms … 457.5 ms 10 runs Benchmark 2: migrate reftable:files (refcount = 100000, revision = HEAD) Time (mean ± σ): 95.2 ms ± 2.2 ms [User: 73.6 ms, System: 20.6 ms] Range (min … max): 91.7 ms … 100.8 ms 28 runs Summary migrate reftable:files (refcount = 100000, revision = HEAD) ran 4.76 ± 0.11 times faster than migrate reftable:files (refcount = 100000, revision = HEAD~) Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'refs/files-backend.c')
-rw-r--r--refs/files-backend.c13
1 files changed, 6 insertions, 7 deletions
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 116d425969..d27806c02c 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -706,7 +706,7 @@ retry:
* reason to expect this error to be transitory.
*/
if (refs_verify_refname_available(&refs->base, refname,
- extras, NULL, err)) {
+ extras, NULL, 0, err)) {
if (mustexist) {
/*
* To the user the relevant error is
@@ -813,7 +813,7 @@ retry:
REMOVE_DIR_EMPTY_ONLY)) {
if (refs_verify_refname_available(
&refs->base, refname,
- extras, NULL, err)) {
+ extras, NULL, 0, err)) {
/*
* The error message set by
* verify_refname_available() is OK.
@@ -850,7 +850,7 @@ retry:
*/
if (refs_verify_refname_available(
refs->packed_ref_store, refname,
- extras, NULL, err)) {
+ extras, NULL, 0, err)) {
ret = TRANSACTION_NAME_CONFLICT;
goto error_return;
}
@@ -1159,7 +1159,7 @@ static struct ref_lock *lock_ref_oid_basic(struct files_ref_store *refs,
*/
if (is_null_oid(&lock->old_oid) &&
refs_verify_refname_available(refs->packed_ref_store, refname,
- NULL, NULL, err))
+ NULL, NULL, 0, err))
goto error_return;
lock->ref_name = xstrdup(refname);
@@ -1538,7 +1538,7 @@ static int refs_rename_ref_available(struct ref_store *refs,
string_list_insert(&skip, old_refname);
ok = !refs_verify_refname_available(refs, new_refname,
- NULL, &skip, &err);
+ NULL, &skip, 0, &err);
if (!ok)
error("%s", err.buf);
@@ -3043,8 +3043,7 @@ static int files_transaction_finish_initial(struct files_ref_store *refs,
BUG("initial ref transaction with old_sha1 set");
if (refs_verify_refname_available(&refs->base, update->refname,
- &affected_refnames, NULL,
- err)) {
+ &affected_refnames, NULL, 1, err)) {
ret = TRANSACTION_NAME_CONFLICT;
goto cleanup;
}