Compare the performance of one or more commands using Linux hardware performance counters, wall-clock time, and peak memory — in a single run.
zbench repeatedly executes each command, measures it with perf_event_open
plus wait4, and prints a colored table of statistics. When you pass more than
one command, every command after the first is compared against the first with a
two-sample t-test, so you can see whether a difference is actually significant.
Linux-only.
From crates.io:
cargo install zbenchOr build from source:
cargo build --release
# binary at target/release/zbenchThe release profile uses thin LTO + panic = "abort" + symbol stripping.
Usage: zbench [options] <command1> ... <commandN>
Compares the performance of the provided commands.
Options:
-d, --duration <ms> (default: 5000) how long to repeatedly sample each command
-r, --runs <n> run each command exactly <n> times (overrides --duration)
-w, --warmup <n> (default: 0) unmeasured warmup runs before sampling each command
--max-runs <n> (default: 10000) cap on samples per command in duration mode
--color <when> (default: auto) color output mode
available options: 'auto', 'never', 'ansi'
-f, --allow-failures (default: false) compare performance even on a non-zero exit code
Commands are split on spaces — there is no shell, so no quoting, globbing,
pipes, or variable expansion. This keeps shell startup out of the measured
numbers; it also means a command like 'sleep 0.1' is sleep with argument
0.1, not a shell string.
# Sample one command for ~2s
zbench -d 2000 ./bench_c
# Compare two builds, exact run count, with warmup
zbench -w 5 -r 200 ./old ./new
# Three-way comparison (first command is the reference)
zbench ./bench_c ./bench_rs ./bench_goEach run reports: wall_time, peak_rss, cpu_cycles, instructions,
cache_references, cache_misses, and branch_misses — as mean ± σ, min … max,
an outlier count (Tukey's fences), and (for comparisons) a delta vs. the
reference. A 💩 marks a significant regression, ⚡ a significant improvement.
- No fixed warmup by default.
zbenchruns each command at least 3 times, then keeps sampling until--durationelapses (capped by--max-runs).--runs <n>switches to an exact count instead.--warmup <n>adds unmeasured priming runs to warm caches / the page cache / the dynamic linker. - Hardware counters are user-space only (
exclude_kernel), opened on the benchmarked process withinherit+enable_on_exec, so counting starts when the childexecves and includes its threads/children. - Peak RSS comes from
wait4'sru_maxrss.zbenchforces afork+execspawn (notposix_spawn) so the reported RSS is the child's, not the parent's.
- Linux with access to
perf_event_open. If your host restricts it, check/proc/sys/kernel/perf_event_paranoid(counters here exclude the kernel, so level2and below are sufficient for unprivileged use). - A recent stable Rust toolchain.
The design and output format are modeled on Andrew Kelley's poop (MIT).
Licensed under the MIT License.
