git/builtin
Karthik Nayak 0e358de64a fetch: use batched reference updates
The reference updates performed as a part of 'git-fetch(1)', take place
one at a time. For each reference update, a new transaction is created
and committed. This is necessary to ensure we can allow individual
updates to fail without failing the entire command. The command also
supports an '--atomic' mode, which uses a single transaction to update
all of the references. But this mode has an all-or-nothing approach,
where if a single update fails, all updates would fail.

In 23fc8e4f61 (refs: implement batch reference update support,
2025-04-08), we introduced a new mechanism to batch reference updates.
Under the hood, this uses a single transaction to perform a batch of
reference updates, while allowing only individual updates to fail.
Utilize this newly introduced batch update mechanism in 'git-fetch(1)'.
This provides a significant bump in performance, especially when dealing
with repositories with large number of references.

Adding support for batched updates is simply modifying the flow to also
create a batch update transaction in the non-atomic flow.

With the reftable backend there is a 22x performance improvement, when
performing 'git-fetch(1)' with 10000 refs:

  Benchmark 1: fetch: many refs (refformat = reftable, refcount = 10000, revision = master)
    Time (mean ± σ):      3.403 s ±  0.775 s    [User: 1.875 s, System: 1.417 s]
    Range (min … max):    2.454 s …  4.529 s    10 runs

  Benchmark 2: fetch: many refs (refformat = reftable, refcount = 10000, revision = HEAD)
    Time (mean ± σ):     154.3 ms ±  17.6 ms    [User: 102.5 ms, System: 56.1 ms]
    Range (min … max):   145.2 ms … 220.5 ms    18 runs

  Summary
    fetch: many refs (refformat = reftable, refcount = 10000, revision = HEAD) ran
     22.06 ± 5.62 times faster than fetch: many refs (refformat = reftable, refcount = 10000, revision = master)

In similar conditions, the files backend sees a 1.25x performance
improvement:

  Benchmark 1: fetch: many refs (refformat = files, refcount = 10000, revision = master)
    Time (mean ± σ):     605.5 ms ±   9.4 ms    [User: 117.8 ms, System: 483.3 ms]
    Range (min … max):   595.6 ms … 621.5 ms    10 runs

  Benchmark 2: fetch: many refs (refformat = files, refcount = 10000, revision = HEAD)
    Time (mean ± σ):     485.8 ms ±   4.3 ms    [User: 91.1 ms, System: 396.7 ms]
    Range (min … max):   477.6 ms … 494.3 ms    10 runs

  Summary
    fetch: many refs (refformat = files, refcount = 10000, revision = HEAD) ran
      1.25 ± 0.02 times faster than fetch: many refs (refformat = files, refcount = 10000, revision = master)

With this we'll either be using a regular transaction or a batch update
transaction. This helps cleanup some code which is no longer needed as
we'll now always have some type of 'ref_transaction' object being
propagated.

One big change is that earlier, each individual update would propagate a
failure. Whereas now, the `ref_transaction_for_each_rejected_update`
function is called at the end of the flow to capture the exit status for
'git-fetch(1)' and also to print F/D conflict errors. This does change
the order of the errors being printed, but the behavior stays the same.

Since transaction errors are now explicitly defined as part of
76e760b999 (refs: introduce enum-based transaction error types,
2025-04-08), utilize them and get rid of custom errors defined within
'builtin/fetch.c'.

Signed-off-by: Karthik Nayak <karthik.188@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-05-19 11:06:31 -07:00
..
add.c builtin/add: remove unnecessary if statement 2025-04-20 14:17:20 -07:00
am.c global: use designated initializers for options 2025-04-17 08:15:15 -07:00
annotate.c
apply.c
archive.c
backfill.c Merge branch 'ps/parse-options-integers' 2025-04-24 17:25:34 -07:00
bisect.c
blame.c Merge branch 'az/tighten-string-array-constness' 2025-04-29 14:21:28 -07:00
branch.c
bugreport.c object-file: move `safe_create_leading_directories()` into "path.c" 2025-04-15 08:24:35 -07:00
bundle.c
cat-file.c treewide: convert users of `repo_has_object_file()` to `has_object()` 2025-04-29 10:08:13 -07:00
check-attr.c
check-ignore.c
check-mailmap.c mailmap: fix check-mailmap with full mailmap line 2025-02-21 18:27:16 -08:00
check-ref-format.c
checkout--worker.c
checkout-index.c builtin/checkout-index: stop using `the_repository` 2025-03-07 16:52:02 -08:00
checkout.c Merge branch 'ps/object-file-cleanup' 2025-04-24 17:25:33 -07:00
clean.c
clone.c Merge branch 'ps/object-store-cleanup' 2025-05-12 14:22:49 -07:00
column.c parse-options: detect mismatches in integer signedness 2025-04-17 08:15:16 -07:00
commit-graph.c Merge branch 'az/tighten-string-array-constness' 2025-04-29 14:21:28 -07:00
commit-tree.c Merge branch 'ps/parse-options-integers' 2025-04-24 17:25:34 -07:00
commit.c global: use designated initializers for options 2025-04-17 08:15:15 -07:00
config.c global: use designated initializers for options 2025-04-17 08:15:15 -07:00
count-objects.c object-store: move function declarations to their respective subsystems 2025-04-29 10:08:12 -07:00
credential-cache--daemon.c object-file: move `safe_create_leading_directories()` into "path.c" 2025-04-15 08:24:35 -07:00
credential-cache.c
credential-store.c
credential.c
describe.c Merge branch 'ps/parse-options-integers' 2025-04-24 17:25:34 -07:00
diagnose.c object-file: move `safe_create_leading_directories()` into "path.c" 2025-04-15 08:24:35 -07:00
diff-files.c
diff-index.c
diff-pairs.c builtin/diff-pairs: allow explicit diff queue flush 2025-03-03 08:17:47 -08:00
diff-tree.c
diff.c hash: stop depending on `the_repository` in `null_oid()` 2025-03-10 13:16:20 -07:00
difftool.c Merge branch 'ua/call-repo-config-with-possibly-null-repository' 2025-04-29 14:21:27 -07:00
fast-export.c Merge branch 'az/tighten-string-array-constness' 2025-04-29 14:21:28 -07:00
fast-import.c object-store: move and rename `odb_pack_keep()` 2025-04-29 10:08:12 -07:00
fetch-pack.c
fetch.c fetch: use batched reference updates 2025-05-19 11:06:31 -07:00
fmt-merge-msg.c parse-options: introduce precision handling for `OPTION_INTEGER` 2025-04-17 08:15:15 -07:00
for-each-ref.c builtin/for-each-ref: stop using `the_repository` 2025-03-07 16:52:02 -08:00
for-each-repo.c
fsck.c Merge branch 'ps/object-wo-the-repository' 2025-04-15 13:50:15 -07:00
fsmonitor--daemon.c
gc.c Merge branch 'ps/object-store-cleanup' 2025-05-12 14:22:49 -07:00
get-tar-commit-id.c
grep.c Merge branch 'ps/parse-options-integers' 2025-04-24 17:25:34 -07:00
hash-object.c object-store: merge "object-store-ll.h" and "object-store.h" 2025-04-15 08:24:37 -07:00
help.c
hook.c
index-pack.c Merge branch 'ds/fix-thin-fix' 2025-05-12 14:22:49 -07:00
init-db.c Merge branch 'ps/parse-options-integers' 2025-04-24 17:25:34 -07:00
interpret-trailers.c
log.c object-store: merge "object-store-ll.h" and "object-store.h" 2025-04-15 08:24:37 -07:00
ls-files.c Merge branch 'ps/object-wo-the-repository' 2025-04-15 13:50:15 -07:00
ls-remote.c global: use designated initializers for options 2025-04-17 08:15:15 -07:00
ls-tree.c object-store: merge "object-store-ll.h" and "object-store.h" 2025-04-15 08:24:37 -07:00
mailinfo.c
mailsplit.c
merge-base.c
merge-file.c object-file: split out functions relating to object store subsystem 2025-04-15 08:24:36 -07:00
merge-index.c
merge-ours.c
merge-recursive.c builtin/merge-recursive: switch to using merge_ort_generic() 2025-04-08 13:59:11 -07:00
merge-tree.c object-store: merge "object-store-ll.h" and "object-store.h" 2025-04-15 08:24:37 -07:00
merge.c Merge branch 'ps/parse-options-integers' 2025-04-24 17:25:34 -07:00
mktag.c object-store: merge "object-store-ll.h" and "object-store.h" 2025-04-15 08:24:37 -07:00
mktree.c Merge branch 'az/tighten-string-array-constness' 2025-04-29 14:21:28 -07:00
multi-pack-index.c Merge branch 'ps/parse-options-integers' 2025-04-24 17:25:34 -07:00
mv.c Merge branch 'ps/mv-contradiction-fix' 2025-05-08 12:36:32 -07:00
name-rev.c Merge branch 'ps/object-wo-the-repository' 2025-04-15 13:50:15 -07:00
notes.c object-store: merge "object-store-ll.h" and "object-store.h" 2025-04-15 08:24:37 -07:00
pack-objects.c Merge branch 'az/tighten-string-array-constness' 2025-04-29 14:21:28 -07:00
pack-redundant.c object-store: merge "object-store-ll.h" and "object-store.h" 2025-04-15 08:24:37 -07:00
pack-refs.c builtin/pack-refs: stop using `the_repository` 2025-03-07 16:52:01 -08:00
patch-id.c
prune-packed.c
prune.c object-store: merge "object-store-ll.h" and "object-store.h" 2025-04-15 08:24:37 -07:00
pull.c refspec: replace `refspec_item_init()` with fetch/push variants 2025-03-21 01:45:16 -07:00
push.c
range-diff.c
read-tree.c global: use designated initializers for options 2025-04-17 08:15:15 -07:00
rebase.c Merge branch 'ps/parse-options-integers' 2025-04-24 17:25:34 -07:00
receive-pack.c treewide: convert users of `repo_has_object_file()` to `has_object()` 2025-04-29 10:08:13 -07:00
reflog.c Merge branch 'ps/maintenance-reflog-expire' 2025-04-16 13:54:19 -07:00
refs.c Merge branch 'sj/ref-consistency-checks-more' 2025-03-26 16:26:10 +09:00
remote-ext.c
remote-fd.c
remote.c treewide: convert users of `repo_has_object_file()` to `has_object()` 2025-04-29 10:08:13 -07:00
repack.c Merge branch 'ps/parse-options-integers' 2025-04-24 17:25:34 -07:00
replace.c object-store: merge "object-store-ll.h" and "object-store.h" 2025-04-15 08:24:37 -07:00
replay.c
rerere.c rerere: let `rerere_path()` write paths into a caller-provided buffer 2025-02-28 13:54:11 -08:00
reset.c
rev-list.c Merge branch 'ps/object-file-cleanup' 2025-04-24 17:25:33 -07:00
rev-parse.c path: drop `git_path()` in favor of `repo_git_path()` 2025-02-28 13:54:11 -08:00
revert.c Merge branch 'ps/parse-options-integers' 2025-04-24 17:25:34 -07:00
rm.c rm: fix sign comparison warnings 2025-03-29 01:04:40 -07:00
send-pack.c builtin/send-pack: stop using `the_repository` 2025-03-07 16:52:01 -08:00
shortlog.c
show-branch.c Merge branch 'az/tighten-string-array-constness' 2025-04-29 14:21:28 -07:00
show-index.c
show-ref.c treewide: convert users of `repo_has_object_file()` to `has_object()` 2025-04-29 10:08:13 -07:00
sparse-checkout.c object-file: move `safe_create_leading_directories()` into "path.c" 2025-04-15 08:24:35 -07:00
stash.c stash: remove merge-recursive.h include 2025-03-17 15:39:03 -07:00
stripspace.c
submodule--helper.c object-store: merge "object-store-ll.h" and "object-store.h" 2025-04-15 08:24:37 -07:00
symbolic-ref.c
tag.c Merge branch 'ps/parse-options-integers' 2025-04-24 17:25:34 -07:00
unpack-file.c object-store: merge "object-store-ll.h" and "object-store.h" 2025-04-15 08:24:37 -07:00
unpack-objects.c treewide: convert users of `repo_has_object_file()` to `has_object()` 2025-04-29 10:08:13 -07:00
update-index.c Merge branch 'ps/parse-options-integers' 2025-04-24 17:25:34 -07:00
update-ref.c refs: add function to translate errors to strings 2025-05-19 11:06:31 -07:00
update-server-info.c builtin/update-server-info: remove unnecessary if statement 2025-04-08 14:47:37 -07:00
upload-archive.c
upload-pack.c
var.c
verify-commit.c builtin/verify-commit: stop using `the_repository` 2025-03-07 16:52:01 -08:00
verify-pack.c
verify-tag.c builtin/verify-tag: stop using `the_repository` 2025-03-07 16:52:01 -08:00
worktree.c object-file: move `safe_create_leading_directories()` into "path.c" 2025-04-15 08:24:35 -07:00
write-tree.c global: use designated initializers for options 2025-04-17 08:15:15 -07:00