[PATCH 0/3] pack-bitmap: boundary-based bitmap traversal
- From
Taylor Blau <me@ttaylorr.com>
- Date
- Apr 25, 2023, 00:00 UTC
- Message-ID
- <cover.1682380788.git.me@ttaylorr.com>
Here is a short (but dense) series that I worked on towards the end of 2021 with Peff.
Its goal is to improve the bitmap traversal we implement in prepare_bitmap_walk(). Specifically, it avoids building up a complete bitmap of the "haves" side, and instead uses a combination of (a) UNINTERESTING commits between the tips and boundary, and (b) the boundary itself.
The gory details are laid out in 3/3, but the high-level overview of the new algorithm to compute the set of objects between "haves" and "wants" using bitmaps is:
1. Build a (partial) bitmap of the haves side by first OR-ing any
bitmap(s) that already exist for UNINTERESTING commits between the
haves and the boundary. 2. For each commit along the boundary, add it as a fill-in traversal
tip (where the traversal terminates once an existing bitmap is
found), and perform fill-in traversal. 3. Build up a complete bitmap of the wants side as usual, stopping any
time we intersect the (partial) haves side.This improves many cases where using bitmaps was significantly *slower* than regular, non-bitmap traversal. In some instances, using bitmaps is still slower than the non-bitmap case, but it is a substantial improvement over the classic bitmap walk.
$ ours="$(git branch --show-current)"
argv="--count --objects $ours --not --exclude=$ours --branches"
hyperfine \
-n 'no bitmaps' "git.compile rev-list $argv" \
-n 'existing bitmap traversal' "git rev-list --use-bitmap-index $argv" \
-n 'this commit' "git.compile rev-list --use-bitmap-index $argv"
Benchmark 1: no bitmaps
Time (mean ± σ): 15.1 ms ± 4.1 ms [User: 8.1 ms, System: 6.9 ms]
Range (min … max): 7.4 ms … 21.8 ms 131 runs Benchmark 2: existing bitmap traversal
Time (mean ± σ): 82.6 ms ± 9.2 ms [User: 63.6 ms, System: 19.0 ms]
Range (min … max): 73.8 ms … 105.4 ms 28 runs Benchmark 3: this commit
Time (mean ± σ): 19.8 ms ± 3.1 ms [User: 13.0 ms, System: 6.8 ms]
Range (min … max): 17.7 ms … 38.6 ms 158 runs Summary
'no bitmaps' ran
1.31 ± 0.41 times faster than 'this commit'
5.49 ± 1.62 times faster than 'existing bitmap traversal'In a large repository on GitHub.com, the timings to compute the objects unique to "master", as in:
$ git rev-list --count --objects master --not --exclude=master --branches
improve as follows:
- 1.012 sec (without bitmaps) - 29.571 sec (with the existing bitmap walk) - 2.279 sec (with these patches)
The first couple of patches are preparatory, and the third patch is the substantive one.
Please have a look and poke any holes you can find in the new approach :-). Thanks in advance for your review.
Taylor Blau (3): revision: support tracking uninteresting commits pack-bitmap.c: extract `fill_in_bitmap()` pack-bitmap.c: use commit boundary during bitmap traversal
pack-bitmap.c | 252 ++++++++++++++++++++++++++++++++++++++------------ revision.c | 10 +- revision.h | 5 + 3 files changed, 205 insertions(+), 62 deletions(-)
-- 2.40.0.380.gda896aa358.dirty