Measured against git
The numbers below are real hyperfine runs of both CLIs on one machine.
Large files & media
The workload mkit is built for: big, incompressible files and small edits to them. Content-defined chunking means a small edit costs the changed chunk, not the whole file — on disk, on the wire, and in wall-clock time.
Time, end to end
Wall-clock time for whole CLI invocations, mean of repeated runs. Lower is better.
commit a 1 MiB change to the 100 MiB file
mkit 5.0× fasterAppend 1 MiB to the already-committed 100 MiB file, then add + commit the new version.
mkit wins by ~5.0×: content-defined chunking re-hashes the file but stores only the changed chunks, so the second version costs about a megabyte. git re-compresses and stores the whole 101 MiB blob again.
add + commit one 1 GiB file
mkit 3.6× fasterSame shape at 1 GiB, 3 runs each.
mkit wins by ~3.6×. First ingest scales linearly for both tools; mkit’s wall clock is I/O + BLAKE3.
add + commit one 100 MiB file
mkit 2.8× fasterA single 100 MiB file of incompressible bytes (a stand-in for video or other compressed media).
mkit wins by ~2.8×: the file splits into ~1,600 content-defined chunks, each hashed with BLAKE3 and barrier-synced from a thread pool, while git’s SHA-1 + zlib pass stays CPU-bound. mkit’s flush cost is constant per commit, not per chunk.
Bytes on disk
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.
Roughly even: incompressible input means zlib buys git nothing, so both stores hold roughly the content plus bookkeeping (the gap is mostly filesystem allocation, not format).
growth after a 1 MiB change
Additional repository bytes after appending 1 MiB to the 100 MiB file and committing the second version.
mkit stores ~1.1 MiB: the appended megabyte, one re-cut boundary chunk, and a fresh manifest. git’s loose store duplicates the whole ~112 MiB blob until git gc repacks it back to ~zero growth, so mkit’s store is incremental by construction while git’s is dense only after a maintenance pass.
Bytes on the wire
What a push sends after a small edit to a large file the remote already holds. Delta-on-the-wire encodes the changed chunk against the version the remote has, instead of re-uploading it whole. 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 rest of the ~1.5 KiB is the new manifest, tree, commit, and packmap node, versus re-sending the whole ~71 KiB re-cut chunk. Delta is a transfer encoding only — it is used only when it beats the raw chunk, and every reconstructed object is re-verified against its hash before storage.
Everyday operations
The routine git operations on ordinary trees, where the honest verdict is roughly even. mkit keeps pace while signing every commit and flushing every object to disk, neither of which git does by default.
Time, end to end
Wall-clock time for whole CLI invocations, mean of repeated runs. Lower is better.
add + commit 100 small files
mkit 1.8× faster100 files of 10 KiB random bytes each, staged and committed in one shot.
mkit wins by ~1.8× while making every commit crash-durable (git does not fsync loose objects by default). Durability is batched behind two fixed full flushes, then renamed into place — git’s core.fsyncMethod=batch design, on by default.
re-add an unchanged 100 MiB file
mkit 1.2× fastertouch the committed file (mtime changes, bytes don’t) and run add again — a pure re-hash.
Close to a tie, mkit a hair ahead: the changed mtime invalidates both tools’ stat caches, so both re-read and re-hash 100 MiB in well under 200 ms and write nothing new.
init an empty repository
about evenmkit init vs git init in a fresh directory.
status with an unchanged 100 MiB file
about evenmkit status / git status in a clean repo holding the committed 100 MiB file, stat cache warm.
A tie. An unchanged file is proven clean by one stat call against the index stat cache — O(stat), no read, no hash, the same trick git plays.
Bytes on disk
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).
Effectively a tie — both store roughly the content plus per-object overhead.
Methodology & caveats
- Signed vs unsigned: every mkit commit is Ed25519-signed; the git side runs unsigned, as git defaults to. Signing costs mkit well under a millisecond per commit, but the comparison is asymmetric.
- Durability: mkit batches each command’s object writes behind 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. Per-object flushing is available via the durability.objects = per-object config key.
- One machine, one filesystem, one day. Ratios on spinning disks, network filesystems, or Linux will differ — flush cost in particular is hardware-dependent.
- Both tools were run through their CLI end to end (process spawn included), with stock configuration: no git core.fsmonitor, no mkit tuning.