Commit 7925306
builtin/cat-file: use bitmaps to efficiently filter by object type
While it is now possible to filter objects by type, this mechanism is
for now mostly a convenience. Most importantly, we still have to iterate
through the whole packfile to find all objects of a specific type. This
can be prohibitively expensive depending on the size of the packfiles.
It isn't really possible to do better than this when only considering a
packfile itself, as the order of objects is not fixed. But when we have
a packfile with a corresponding bitmap, either because the packfile
itself has one or because the multi-pack index has a bitmap for it, then
we can use these bitmaps to improve the runtime.
While bitmaps are typically used to compute reachability of objects,
they also contain one bitmap per object type encodes which object has
what type. So instead of reading through the whole packfile(s), we can
use the bitmaps and iterate through the type-specific bitmap. Typically,
only a subset of packfiles will have a bitmap. But this isn't really
much of a problem: we can use bitmaps when available, and then use the
non-bitmap walk for every packfile that isn't covered by one.
Overall, this leads to quite a significant speedup depending on how many
objects of a certain type exist. The following benchmarks have been
executed in the Chromium repository, which has a 50GB packfile with
almost 25 million objects:
Benchmark 1: git cat-file --batch-check --batch-all-objects --unordered --buffer --no-objects-filter
Time (mean ± σ): 82.806 s ± 6.363 s [User: 30.956 s, System: 8.264 s]
Range (min … max): 73.936 s … 89.690 s 10 runs
Benchmark 2: git cat-file --batch-check --batch-all-objects --unordered --buffer --objects-filter=object:type=tag
Time (mean ± σ): 20.8 ms ± 1.3 ms [User: 6.1 ms, System: 14.5 ms]
Range (min … max): 18.2 ms … 23.6 ms 127 runs
Benchmark 3: git cat-file --batch-check --batch-all-objects --unordered --buffer --objects-filter=object:type=commit
Time (mean ± σ): 1.551 s ± 0.008 s [User: 1.401 s, System: 0.147 s]
Range (min … max): 1.541 s … 1.566 s 10 runs
Benchmark 4: git cat-file --batch-check --batch-all-objects --unordered --buffer --objects-filter=object:type=tree
Time (mean ± σ): 11.169 s ± 0.046 s [User: 10.076 s, System: 1.063 s]
Range (min … max): 11.114 s … 11.245 s 10 runs
Benchmark 5: git cat-file --batch-check --batch-all-objects --unordered --buffer --objects-filter=object:type=blob
Time (mean ± σ): 67.342 s ± 3.368 s [User: 20.318 s, System: 7.787 s]
Range (min … max): 62.836 s … 73.618 s 10 runs
Benchmark 6: git cat-file --batch-check --batch-all-objects --unordered --buffer --objects-filter=blob:none
Time (mean ± σ): 13.032 s ± 0.072 s [User: 11.638 s, System: 1.368 s]
Range (min … max): 12.960 s … 13.199 s 10 runs
Summary
git cat-file --batch-check --batch-all-objects --unordered --buffer --objects-filter=object:type=tag
74.75 ± 4.61 times faster than git cat-file --batch-check --batch-all-objects --unordered --buffer --objects-filter=object:type=commit
538.17 ± 33.17 times faster than git cat-file --batch-check --batch-all-objects --unordered --buffer --objects-filter=object:type=tree
627.98 ± 38.77 times faster than git cat-file --batch-check --batch-all-objects --unordered --buffer --objects-filter=blob:none
3244.93 ± 257.23 times faster than git cat-file --batch-check --batch-all-objects --unordered --buffer --objects-filter=object:type=blob
3990.07 ± 392.72 times faster than git cat-file --batch-check --batch-all-objects --unordered --buffer --no-objects-filter
The first benchmark is mostly equivalent in runtime compared to all the
others without the bitmap-optimization introduced in this commit. What
is noticeable in the benchmarks is that we're I/O-bound, not CPU-bound,
as can be seen from the user/system runtimes, which is often way lower
than the overall benchmarked runtime.
Signed-off-by: Patrick Steinhardt <[email protected]>
Signed-off-by: Junio C Hamano <[email protected]>1 parent 1061745 commit 7925306
1 file changed
+50
-5
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
| 24 | + | |
24 | 25 | | |
25 | 26 | | |
26 | 27 | | |
| |||
805 | 806 | | |
806 | 807 | | |
807 | 808 | | |
808 | | - | |
| 809 | + | |
| 810 | + | |
| 811 | + | |
| 812 | + | |
| 813 | + | |
| 814 | + | |
| 815 | + | |
| 816 | + | |
| 817 | + | |
| 818 | + | |
| 819 | + | |
| 820 | + | |
| 821 | + | |
| 822 | + | |
809 | 823 | | |
810 | 824 | | |
811 | 825 | | |
812 | 826 | | |
813 | 827 | | |
814 | 828 | | |
815 | 829 | | |
| 830 | + | |
| 831 | + | |
816 | 832 | | |
817 | | - | |
818 | | - | |
| 833 | + | |
| 834 | + | |
| 835 | + | |
| 836 | + | |
| 837 | + | |
| 838 | + | |
| 839 | + | |
| 840 | + | |
| 841 | + | |
| 842 | + | |
| 843 | + | |
| 844 | + | |
| 845 | + | |
| 846 | + | |
| 847 | + | |
| 848 | + | |
| 849 | + | |
| 850 | + | |
| 851 | + | |
| 852 | + | |
| 853 | + | |
| 854 | + | |
| 855 | + | |
| 856 | + | |
| 857 | + | |
| 858 | + | |
| 859 | + | |
| 860 | + | |
| 861 | + | |
| 862 | + | |
| 863 | + | |
819 | 864 | | |
820 | 865 | | |
821 | 866 | | |
| |||
872 | 917 | | |
873 | 918 | | |
874 | 919 | | |
875 | | - | |
| 920 | + | |
876 | 921 | | |
877 | 922 | | |
878 | 923 | | |
879 | 924 | | |
880 | 925 | | |
881 | 926 | | |
882 | | - | |
| 927 | + | |
883 | 928 | | |
884 | 929 | | |
885 | 930 | | |
| |||
0 commit comments