Performance compared with Git
Command durations, storage sizes, and transfer sizes measured on one machine with hyperfine and the repository benchmark scripts.
Large files and media
Large, incompressible files and small edits. Content-defined chunking lets mkit reuse unchanged chunks when storing and transferring a new version.
Command duration
Mean wall-clock time over repeated runs of each CLI command, including process startup. Lower is better.
Commit a 1 MiB change to the 100 MiB file
mkit 19.1× fasterAppend 1 MiB to the already-committed 100 MiB file, then add and commit the new version.
Content-defined chunking re-hashes the file but stores only changed chunks, adding about 1 MiB. Git compresses and stores the full 101 MiB blob again. File rewrite costs depend on the storage system.
Add and commit one 1 GiB file
mkit 10.1× fasterAdd and commit a 1 GiB file of incompressible bytes, with 3 runs per tool.
Time scales linearly with file size for both tools. mkit’s time goes to file I/O and BLAKE3 hashing. With only 3 runs, mkit’s standard deviation is large (1.04 s on a 3.52 s mean), but the ranges (2.7–4.7 s vs 35.5–36.0 s) do not overlap.
Add and commit one 100 MiB file
mkit 7.6× fasterThe file holds incompressible bytes, standing in for video or other compressed media.
mkit divides the file into roughly 1,300 chunks, hashes each with BLAKE3, and syncs writes to disk from a thread pool. Git’s SHA-1 hashing and zlib compression are CPU-bound. Run-to-run variation was lower in this measurement (a 43 ms standard deviation on a 373 ms mean), but shared disk I/O still affects these timings.
Checkout a branch that changed a 100 MiB file
about evenmain has a committed 100 MiB file; branch v2 appends 1 MiB to it. Measures checking out v2 from main.
In this measurement git is about 14% faster, but mkit’s standard deviation is 166 ms on a 412 ms mean (runs ranged from 261 to 783 ms), so the two overlap and the data does not support a reliable winner. On 2026-09-19 a separate run (mkit commit d7afae5, same container class) measured mkit about 6% faster; the two runs disagree, which is consistent with noise. Restoring a ChunkedBlob writes every chunk to one shared file sequentially, and only each chunk’s read-and-verify step runs in parallel. cargo bench -p mkit-benches --bench restore_chunk_fanout measures that step alone: a 128 MiB restore’s chunk-read phase drops from 115.3 ms to 83.2 ms (about 28%). This row measures the full add, commit, checkout, and git process-spawn round trip end to end.
Storage size
Repository directory size (du -k .mkit vs .git) after the same operations. Lower is better.
One 100 MiB file, one commit
Repository size after the first commit of the 100 MiB file.
Git uses slightly less storage in this measurement. zlib does not reduce the incompressible content. mkit stores roughly 1,300 chunk objects, while Git stores one loose blob. Each file occupies whole 4 KiB filesystem blocks, so mkit’s chunk files add more overhead on ext4 than in the previous APFS measurement.
Growth after a 1 MiB change
Additional repository bytes after appending 1 MiB to the 100 MiB file and committing the second version.
mkit adds about 1.2 MiB: the appended data, one changed boundary chunk, and a new manifest. Git’s loose object store adds the full 101 MiB blob. After git gc, Git’s growth falls to about 1.0 MiB, similar to mkit.
Transfer size
Bytes a push sends after a small edit to a large file the remote already has. With delta encoding, mkit sends the changed chunk as a delta against the remote’s copy instead of the whole chunk. Lower is better.
Push a 16-byte edit to a 2 MiB file
47× smaller pushEdit 16 bytes in the middle of a 2 MiB FastCDC-chunked file the remote already holds, then push the new commit. Bytes counted on the wire.
The chunk delta is 93 bytes. The new manifest, tree, commit, and packmap node bring the transfer to about 1.5 KiB, compared with about 71 KiB for the changed chunk. Delta encoding applies only to transfers and only when it is smaller than the raw chunk. The receiver verifies each reconstructed object’s hash before storage.
Everyday operations
Common operations on small files and unchanged repositories. mkit signs every commit and flushes object writes to disk. In these benchmarks Git uses its defaults: unsigned commits and no fsync for loose objects.
Command duration
Mean wall-clock time over repeated runs of each CLI command, including process startup. Lower is better.
Add and commit 100 small files
mkit 2.4× faster100 files of 10 KiB random bytes each, staged and committed together.
mkit makes each commit crash-durable by default with two full flushes before renaming objects into place, following Git’s core.fsyncMethod=batch design. Git does not fsync loose objects by default.
Re-add an unchanged 100 MiB file
mkit 2.4× fasterRun touch on the committed file to change its modification time without changing its contents, then run add to re-hash it.
The changed modification time invalidates both stat caches, so both tools read and hash the full 100 MiB again. Git’s SHA-1 pass takes longer than mkit’s BLAKE3 pass on this CPU.
Initialize an empty repository
mkit 1.2× fastermkit init vs git init in a fresh directory.
Both commands finish in a few milliseconds, below hyperfine’s roughly 5 ms shell calibration threshold. mkit’s slowest run was about 7 ms across 332 runs. These timings do not support a reliable speed comparison.
Status with an unchanged 100 MiB file
git 1.2× fastermkit status and git status in a clean repository containing the committed 100 MiB file, with a warm stat cache.
Both timings are below hyperfine’s roughly 5 ms shell calibration threshold. Both tools check cached file metadata with one stat call, without reading or hashing file contents.
Storage size
Repository directory size (du -k .mkit vs .git) after the same operations. Lower is better.
100 small files, one commit
Repository size after committing 100 × 10 KiB of random bytes (1,000 KiB of content).
Both repositories use similar storage: the content size plus per-object overhead.
Core microbenchmarks
Criterion benchmarks of a single mkit code path, comparing mkit against its own previous commit rather than Git. Median time; lower is better.
List 100 branch refs
23% fasterlist_refs over 100 ref files on a warm page cache.
List 1,000 branch refs
15% fasterlist_refs over 1,000 ref files on a warm page cache.
List 10,000 branch refs
23% fasterlist_refs over 10,000 ref files on a warm page cache.
Measured 2026-09-28 with cargo bench -p mkit-benches --bench refs_ops on the same class of 4-core container as the methodology below. Each ref file is now read with one stack-buffer read (open, read, close) instead of fs::read, which adds a size-hint statx and an end-of-file probe read. About 23% faster at 10,000 refs and 25% at 100; the 1,000-ref run shows 15%.
Methodology and limitations
- Date
- Sep 28, 2026
- Commit
a693e2eb- Machine
- 4-core Intel Xeon @ 2.10 GHz, 15 GB RAM, ext4 on a virtual disk, Linux 6.18 (Ubuntu 24.04). A shared virtualized container.
- Versions
- mkit 0.4.2 (release build, cargo build --release) · git 2.43.0 · hyperfine 1.20.0
- Harness
- scripts/bench-vs-git.sh — hyperfine with --warmup and per-command --prepare resetting a temp directory to a clean state between runs; 3 runs for the 1 GiB case, hyperfine defaults elsewhere; results from --export-json. Sizes via du -k.
- Workload
- Random (incompressible) bytes, representing already-compressed media such as video. Compressible content such as source code may compress better in Git’s zlib store; these benchmarks do not measure it.
- Signing: every mkit commit is Ed25519-signed; Git commits are unsigned, which is Git’s default. Signing adds well under a millisecond per mkit commit, but the two sides do different work.
- Durability: mkit batches each command’s object writes using two fixed full flushes plus per-file barriers (SPEC-OBJECTS §10.1), so a commit is durable when the command returns; Git does not fsync loose objects by default. To flush each object individually, set durability.objects = per-object.
- Results are from one shared virtualized container. Scheduling and disk contention affect timings. Other hardware, operating systems, and filesystems may produce different ratios. Flush costs and small-file block-size overhead depend on the hardware and filesystem.
- Both tools ran as CLI processes end to end, including process startup, with default configuration: no Git core.fsmonitor and no mkit tuning.