connected: do not sort input revisions
In order to compute whether objects reachable from a set of tips are all connected, we do a revision walk with these tips as positive references and `--not --all`. `--not --all` will cause the revision walk to load all preexisting references as uninteresting, which can be very expensive in repositories with many references. Benchmarking the git-rev-list(1) command highlights that by far the most expensive single phase is initial sorting of the input revisions: after all references have been loaded, we first sort commits by author date. In a real-world repository with about 2.2 million references, it makes up about 40% of the total runtime of git-rev-list(1). Ultimately, the connectivity check shouldn't really bother about the order of input revisions at all. We only care whether we can actually walk all objects until we hit the cut-off point. So sorting the input is a complete waste of time. Introduce a new "--unsorted-input" flag to git-rev-list(1) which will cause it to not sort the commits and adjust the connectivity check to always pass the flag. This results in the following speedups, executed in a clone of gitlab-org/gitlab [1]: Benchmark #1: git rev-list --objects --quiet --not --all --not $(cat newrev) Time (mean ± σ): 7.639 s ± 0.065 s [User: 7.304 s, System: 0.335 s] Range (min … max): 7.543 s … 7.742 s 10 runs Benchmark #2: git rev-list --unsorted-input --objects --quiet --not --all --not $newrev Time (mean ± σ): 4.995 s ± 0.044 s [User: 4.657 s, System: 0.337 s] Range (min … max): 4.909 s … 5.048 s 10 runs Summary 'git rev-list --unsorted-input --objects --quiet --not --all --not $(cat newrev)' ran 1.53 ± 0.02 times faster than 'git rev-list --objects --quiet --not --all --not $newrev' [1]: https://gitlab.com/gitlab-org/gitlab.git. Note that not all refs are visible to clients. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
29ef1f27fe
commit
f45022dc2f
@ -169,4 +169,35 @@ test_expect_success 'rev-list --count --objects' '
|
||||
test_line_count = $count actual
|
||||
'
|
||||
|
||||
test_expect_success 'rev-list --unsorted-input results in different sorting' '
|
||||
git rev-list --unsorted-input HEAD HEAD~ >first &&
|
||||
git rev-list --unsorted-input HEAD~ HEAD >second &&
|
||||
! test_cmp first second &&
|
||||
sort first >first.sorted &&
|
||||
sort second >second.sorted &&
|
||||
test_cmp first.sorted second.sorted
|
||||
'
|
||||
|
||||
test_expect_success 'rev-list --unsorted-input incompatible with --no-walk' '
|
||||
cat >expect <<-EOF &&
|
||||
fatal: --no-walk is incompatible with --unsorted-input
|
||||
EOF
|
||||
test_must_fail git rev-list --unsorted-input --no-walk HEAD 2>error &&
|
||||
test_cmp expect error &&
|
||||
test_must_fail git rev-list --unsorted-input --no-walk=sorted HEAD 2>error &&
|
||||
test_cmp expect error &&
|
||||
test_must_fail git rev-list --unsorted-input --no-walk=unsorted HEAD 2>error &&
|
||||
test_cmp expect error &&
|
||||
|
||||
cat >expect <<-EOF &&
|
||||
fatal: --unsorted-input is incompatible with --no-walk
|
||||
EOF
|
||||
test_must_fail git rev-list --no-walk --unsorted-input HEAD 2>error &&
|
||||
test_cmp expect error &&
|
||||
test_must_fail git rev-list --no-walk=sorted --unsorted-input HEAD 2>error &&
|
||||
test_cmp expect error &&
|
||||
test_must_fail git rev-list --no-walk=unsorted --unsorted-input HEAD 2>error &&
|
||||
test_cmp expect error
|
||||
'
|
||||
|
||||
test_done
|
||||
|
Reference in New Issue
Block a user