Repository navigation
Releases: johnservil/bench-hashes
Release list
bench-hashes 0.16.1
New in 0.16 (since 0.15.3):
- A new contender, BLAKE3 commonware: the batch kernels of commonware's cryptography crate (pull request #4982), measured on batches of 64-byte messages, so that their author can compare them with BLAKE3 servil's on x86-64 machines.
--allincludes it;--contenders blake3-commonware,...picks it. - The map explains itself: point at (or tap) a row's or a column's name to see what it means; clicking no longer greys a row or column. Escape puts an open chart back.
- Each run's line names the machine, its OS, the day, and how many seconds other programs kept it busy; "About this run" holds the provenance (the release, the commits, the crates, the compiler, the power, the load in full), linked to the exact code.
- Two runs side by side:
bench-hashes map NEW --beside OLDdraws the older run's lines dashed under the newer one's, with both values under the pointer. This release's: Apple M4 Max, Linux VM.
Records: the fork at servil 9d9f3d6, measured with this release (Apple M4 Max on mains, quiet; the VM, quiet). The fork's b3sum now hashes several files at once; on the Mac, against 0.15.3's records:
- a tree of 1000 files of 16 KiB: in the page cache 1.17 -> 0.75 ns/B, read from storage 5.90 -> 1.72
- a mixed tree of 1000 files, 74 MiB: in the page cache 0.318 -> 0.150, from storage 1.28 -> 0.376
- single files level
The hashing code is 0.15.3's, so the library's cells move only by run-to-run noise. The queue's cells read up to 2x apart between runs of identical code (pipelined 256 B 0.170-0.295 ns/B, batches of 16 4.2-8.8 ns a message, Mac jobs 1428 and 1431); this record reads pipelined 256 B 0.322 against 0.180, 1 KiB 0.141 against 0.110, within that spread. Cells after a pause move 10-20% either way between runs.
Maps: Apple M4 Max, Linux VM on it.
bench-hashes 0.15.3
The map's touch: on a touch screen a tap on an open chart shows the values at its point, and the chart's button puts it back. The benchmark's measurements are 0.15.0's.
Records: the fork at servil 6d9cac3, measured with this release. Against 0.15.2's records on an Apple M4 Max (one run each; BLAKE3 servil's better contender, ns per byte or per message):
- pipelined batches of 16: 8.32 -> 4.66 ns a message; of 64: 5.30 -> 3.76; of 256: 3.75 -> 2.83
- pipelined messages: 64 B 0.758 -> 0.516 ns/B, 16 KiB 0.104 -> 0.071, 64 KiB 0.060 -> 0.045, 64 MiB 0.057 -> 0.041
- two programs at once: pipelined 64 B 1.12 -> 0.74, 64 MiB 0.097 -> 0.072, batches of 64 7.9 -> 5.5
- slower: two programs, pipelined 4 KiB 0.123 -> 0.159 (the queue's own trade); cells after a pause move 10-20% either way between runs
Against SHA-256, one cell changed hands for good: pipelined 64-byte messages, now BLAKE3 servil's (0.516 against 0.579). The others that changed hands (small batches after a pause, two programs' many messages at once) were ties within the run-to-run noise.
Maps: Apple M4 Max, Linux VM on it.
bench-hashes 0.15.2
The map's words alone: the first column reads "now and then, after other work", as the second reads "now and then, after a pause". The benchmark's measurements are 0.15.0's.
Records: the fork at servil 081ffcd, measured with this release: small batches after a pause run on the pair kernel alone, and the one-chunk kernel's rounds run as a loop (a quarter of its code). Against the previous records on an Apple M4 Max (one run each):
- one message after other work: 64 B 14.5 -> 10.1 ns/B, 256 B 4.04 -> 3.01, 1 KiB 1.59 -> 1.32
- a batch after other work, ns per message: 2 messages 337 -> 283, 4 messages 220 -> 168
- a batch after a pause: 4 messages 279 -> 174 ns per message
- nonstop 64 B +3.6% and 1 KiB +2.1% (accepted: the same call)
Maps: Apple M4 Max, Linux VM on it.
bench-hashes 0.15.1
The regression check alone changes: a pair with a run that clocks found busy runs again, up to three times (on the Mac a process launch now and then puts about 1.7 CPU-seconds of other programs' work inside a run's window). The benchmark's measurements and the map are 0.15.0's.
Records: the fork after its optimisation pass (servil 684274a), measured with this release. Against 0.15.0's baseline on an Apple M4 Max, ns/B:
- many messages at once: 0.516 -> 0.268 (SHA-256 ring 0.310)
- a collection, BLAKE3 servil mt: git objects 0.229 -> 0.040, Nix files 0.219 -> 0.049 (SHA-256 ring 0.295, 0.293)
- pipelined 16 KiB messages: 0.147 -> 0.119
Maps: Apple M4 Max, Linux VM on it; 0.15.0's baseline maps stay in its tag.
bench-hashes 0.15.0
The benchmark frozen for an optimisation pass of the servil fork: its maps before and after the fork's changes come from this one benchmark.
- A message received, verified as it arrives (new row): iroh-blobs' wire format (bao-tree's pre-order encoding, 16 KiB groups) arriving in 64 KiB pieces, verified against the message's hash, each verified group copied into the message's buffer. bao-tree 0.16.1's
decode_rangesagainst the fork'sVerifier. - Many messages at once arrive in turns of 64 pieces, each in its own buffer, as one wait of a server's event loop delivers them; BLAKE3 servil takes each turn in one call (
Hasher::update_each, thenHasher::finalize_each). Every contender's numbers move a little from 0.14's. - A collection, multithreaded, in one call: BLAKE3 servil mt uses
hash_each_multithreaded_with, the twin of servil st'shash_each_with.
Records: the Mac and the VM, fork servil 5454196, before the pass. Maps: Apple M4 Max, Linux VM on it.
bench-hashes 0.14.1
The map only; the measurements are 0.14.0's, and the records' maps are redrawn from their samples.
- Every chart of a section shares one rate axis, in GB/s (a batch's rate is its messages' bytes per second), with faint lines at each power of ten: a line's height reads the same in every chart.
- The outboards' BLAKE3 line is named bao-tree (iroh-blobs), its own contender in its own colour: the BLAKE3 contender builds outboards with bao-tree, the crate iroh-blobs uses.
Maps: Apple M4 Max, Linux VM on it.
bench-hashes 0.14.0
The map. Every run writes bench-hashes.map.html: a small chart for each way a program hashes, its rows what the program hashes, its columns how it calls. Click a chart to open it in place, with the exact values under the pointer; each call's name links to its documentation. A bench-hashes b3sum run adds a section for b3sum in the same form. The map replaces the graph, the guide's chart, and b3sum's bar chart; the guide's answers link to their charts on it.
New measurements:
- A collection of items of different lengths, each hashed once: git's objects and Nix's store files, in their real shares by size.
- Messages with their outboards, for verified streaming (the layout iroh-blobs stores).
- Many messages at once, each arriving in pieces, as a server receives uploads. It replaces one long message in pieces.
- b3sum with a process per file, as a shell loop runs it.
Every cell now charges the program's work around the hash: the write of its input, after a gap as in every nonstop cell, and the use of each hash, stored in its message's slot. So cells after a gap read slower than in 0.13.0, by the write. Compare results only release with release.
Records (Apple M4 Max on mains, and a Linux VM on it), measured from commit 7722f10, the code of 0.14.0 before its version commits, against the servil fork at 31f5a25. On the M4 Max:
- a repository's objects hash at 0.226 ns per byte with BLAKE3 servil's
hash_each_with, against SHA-256's 0.293; - outboards of 64 MiB at 0.041 ns per byte, against bao-tree's 0.410.
bench-hashes 0.13.0
Charts to look at and to share, drawn from the samples files (FROZEN.md, "Changes since 0.12.0"); the measurements are 0.12.0's.
bench-hashes.chart.svg: one 1 MiB message after other work, BLAKE3 servil on every core and on one, beside the fastest measured SHA-256, SHA3-256, and SHA-1, as bars in GB/s from each cell's mean. Every full run draws it.b3sum.chart.svg: how fast b3sum hashes files from its start to its exit, warm and cold, a row for each input and a bar for each build, labelled with its time per run and its ratio to the first build. Everybench-hashes b3sumrun draws it.bench-hashes chart SAMPLES.tsvdraws either again from a stored samples file.
Records: the hash records of 0.12.0 (Apple M4 Max, job 1174, and a Linux VM on it) with their charts, and new b3sum records on both: official b3sum 1.8.2 against the servil fork's at eb5e0af, 15 rounds, quiet. On the M4 Max the fork's b3sum hashes a 1 GiB file read from storage in 159 ms against 385, a tree of 1000 small files in the page cache in 19.1 ms against 60.8.
bench-hashes 0.12.0
The benchmark of 0.11.0 with one summary, one regression check, and b3sum, decided on October 2, 2026 from the regression check's calibration (FROZEN.md, "Changes since 0.11.0"; the fork's NOTES, "The regression check, calibrated"). It measures the servil fork at eb5e0af.
One summary. Every figure is a run's mean: the total time of its samples over the total work they did, what a program pays on average. The two-speed rule and its cut-offs are gone, with the graph's second line, its footnote, and the guide's fainter dots. Results of 0.11.0 and earlier were medians, speed by speed: compare them only release with release.
One regression check. bench-hashes regress OLD NEW runs eight pairs of runs, one of each build, back to back in alternating order, over the lent cells, one copy alone. A cell is slower when the median of its pairs' ratios exceeds 3% and an exact sign test agrees (seven of eight pairs). Calibrated with planted slowdowns and builds of identical code, eight repeats each: identical executables never held (Mac 0 of 5, VM 0 of 8); a layout-only change held 1 time in 8 on the Mac, 0 in the VM; +3% held 4 of 7 (Mac) and 5 of 8 (VM); +6% every time. A check takes about 30 s.
Measured better. Each cell's samples are sized after one untimed call of its batch, so first-use costs no longer shorten them (Devon Jonte's finding: the queue's 64-byte samples were a fifth of their intended length). compare names any run whose load was unmeasured, as well as busy.
b3sum. bench-hashes b3sum NAME=COMMAND... times builds of the BLAKE3 command-line tool as you run them, start to exit, on fixed files and directory trees, warm and cold (README, "How fast is b3sum?").
Records: Apple M4 Max (macOS, runner job 1174) and a Linux VM on it, both --all, both quiet.
bench-hashes 0.11.0
The benchmark of 0.10.0 with two changes Zooko decided on October 2, 2026 (FROZEN.md, "Changes since 0.10.0"), measuring the servil fork at 44ab752 (0.10.0 measured b132f8c).
What it measures differently
- The programs' kept buffers are written when made. The queue's batch buffers and digest space, its message buffers, and the lent pieces' read buffer came from zeroed allocations, whose pages the system maps at their first write, so each cell's first sample paid page faults no real program's kept buffers pay. On an Apple M4 Max, shared queue batches of 65536 messages lose a slow speed of 46.3 ns per message in a tenth of their samples (now 6.4).
- The fork's queue is called with a mode and a handler,
Queue::messages(Mode::Hash, handler): the fork removed its time-or-energy choice, and the benchmark's calls were already the time form. The guide asks four questions; its "time or energy?" question is gone.
What it shows of the fork since b132f8c (the fork's CHANGELOG has each): one-shot calls of 1-64 KiB after other work take 40-50% less time; inputs much larger than the caches on one thread about 10% less; extended output 4.5x as fast on Apple M4 and later.
Records: Apple M4 Max (macOS, runner job 1145) and a Linux VM on it, both --all, both quiet: benchmark-results/, and the graphs on the Pages site.
Results of 0.10.0 and of 0.11.0 measure different things in the queue's cells: compare them only release with release.