Resolve packs ~6 times faster than Git* #2854
Pinned
Sebastian Thiel (Byron)
started this conversation in
Show and tell
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
*with 16 cores and SHA-256. This should scale, so I wouldn't be surprised to see even higher numbers with 64 cores.
And while what follows what LLM written, it's reviewed and tuned by me.
Operations that read an entire pack—such as cloning, fetching, indexing, connectivity checking, and pack verification—spend substantial time resolving delta-compressed objects.
gixnow resolves these delta trees lazily and distributes branches across idle workers. This keeps cores productive even when a pack ends with one deep, expensive delta tree, without retaining an entire frontier of resolved bases.gixgixefficiencyOn the pathological pack,
gixretains 97.3% efficiency at eight threads, compared with Git’s 58.2%. At 16 threads,gixretains 77.6% while Git falls to 36.1%.The pattern holds across the other packs:
gixkeeps more useful work on each additional core, while Git’s wall-clock scaling flattens earlier.Why SHA-256 is included
The SHA-1 and SHA-256 results come from the same private 10.9M-object Linux pack. The SHA-256 version preserves the compressed object data and delta topology byte-for-byte; only the pack trailer and index use SHA-256. This keeps scheduling and delta work constant, isolating the cost of hashing every reconstructed object.
Within
gix, the SHA-256 resolver is 2.72×–2.99× faster than SHA-1 across the measured thread counts. This shows that hashing—not work distribution—is responsible for much of the remaining absolute SHA-1 cost. It also gives a preview of pack processing as repositories begin adopting Git’s SHA-256 object format.For fairness, Git’s SHA-256 measurements use an OpenSSL-backed build. The portable backend in the original local Git build was substantially slower and would have exaggerated the difference.
All measurements were taken sequentially on the same ARM64 macOS host with 16 logical cores.
Footnotes
Efficiency is calculated from wall time as
serial time / (thread count × parallel time). At 100%, doubling the cores halves wall time. Unlike resolver-only timing, this includes fixed command and index-processing overhead for both implementations. Git efficiency is unavailable for the private SHA-1 pack because its serial Git run was not recorded. ↩The phpstan pack contains 100.7k objects and expands to 174.6 GB. Git’s 1/2/4/8/16-thread series used per-worker delta-base cache limits of 768/384/192/96/96 MiB, ensuring at least the default eight-thread aggregate allowance of 768 MiB. Commands:
/usr/bin/time -lp git -c core.deltaBaseCacheLimit=<limit> index-pack --verify --threads=<threads> <pack>and/usr/bin/time -lp gix -t<threads> -v free pack verify <index>. ↩This fixture contains 7.6M objects, expands to 95.6 GB, and is distributed with gitoxide as
tests/fixtures/repos/linux.git/objects/pack/pack-3ee05b0f4e4c2cb59757c95c68e2d13c0a491289. Commands:/usr/bin/time -lp git index-pack --verify --threads=<threads> <pack>and/usr/bin/time -lp gix -t<threads> -v free pack verify <index>. ↩This private 10.9M-object Linux pack is retained locally as a long-term benchmarking fixture and is not distributed with gitoxide. It expands to 146.7 GB and is identified locally as
pack-6f64e91eccd8f68e174dc2c01416b392c66867e7. Git’s measurement used its default eight resolver threads. Commands:/usr/bin/time -lp git index-pack --verify --threads=8 <pack>and/usr/bin/time -lp gix --object-hash sha1 -t8 -v free pack verify <index>. ↩The private SHA-256 fixture is intended for pack verification, not as a converted repository: commit and tree payloads still contain SHA-1 references. Git was built from
cf5497b14cwithSHA1_DCand OpenSSL 3.6.3’sSHA256_OPENSSLbackend. Switching from its portableSHA256_BLKbackend reduced Git’s eight-thread wall time from 144.15 to 40.45 seconds. Commands:/usr/bin/time -lp git index-pack --verify --object-format=sha256 --threads=<threads> <pack>and/usr/bin/time -lp gix --object-hash sha256 -t<threads> -v free pack verify <index>. ↩All reactions