snailrace benchmarks commands on Linux and macOS. It measures time, CPU,
memory, process structure, and static disk footprint.
brew install shellcell/tap/snailraceEnable the shellcell repository once — setup instructions at https://packages.shellcell.dev — then:
sudo apt install snailrace # Debian / Ubuntu
sudo dnf install snailrace # Fedora / RHEL
sudo apk add snailrace # AlpineWith an AUR helper (e.g. paru or yay):
paru -S snailrace # builds from source
paru -S snailrace-bin # prebuilt binaryOr manually:
git clone https://aur.archlinux.org/snailrace.git # or snailrace-bin.git
cd snailrace && makepkg -sigo install github.com/shellcell/snailrace/cmd/snailrace@latest # Go 1.22+Download the archive for your OS/arch from Releases; each contains the binary, man page, and shell completions. To build from source, see Build below.
Requires Go 1.22+. macOS also requires a C compiler for the cgo libproc
sampler.
make buildBenchmark one command:
./snailrace -n 20 -warmups 3 -- gzip -k sample.txtCompare shell commands:
./snailrace -n 20 -c 'grep needle data.txt' -c 'rg needle data.txt'An HTML report is saved to the current directory by default. Choose another directory:
./snailrace -format html -output ./reports -- ./my-program --flagUse -no-save when only stdout output is wanted.
Measure an interactive TUI:
./snailrace tui -- htop
./snailrace tui -duration 30s -n 5 -c htop -c btop| Option | Purpose |
|---|---|
-c, -command |
Shell command; repeat to compare |
-label |
Command display label |
-prepare |
One-time setup command |
-n, -runs |
Measured runs; default 10 |
-warmups |
Warmup runs; default 1 |
-interval |
Sampling interval; default 10 ms |
-index |
Index dimensions: time,cpu,ram,disk |
-baseline |
1-based baseline; 0 selects the winner |
-f, -format |
Saved format; default html |
-o, -output |
Report directory; default current directory |
-no-save |
Do not save report files |
-verbose |
Full statistical tables on stdout |
-show-output |
Forward command output to stderr |
tui |
Run inside a pseudo-terminal |
-d, -duration |
Fixed TUI duration |
-width, -height |
TUI geometry |
| Group | Metrics |
|---|---|
| Time | Wall time |
| CPU | User, system, total, average utilization |
| Memory | Mean/peak tree RSS, OS max RSS, peak virtual memory |
| macOS memory | Peak aggregate physical footprint |
| Structure | Peak processes, threads, file descriptors where available |
| Disk | Executable and statically linked dynamic-library files |
Raw runs and summary statistics are available in JSON. Reports include mean, sample standard deviation, median, p95, range, and a 95% Student's t interval. Every format identifies the dimensions actually included in the balanced index and records sampling or metric-availability caveats.
- Runs use randomized counterbalanced order.
- The default index combines normalized time, CPU, and RAM costs.
- RAM cost combines mean and peak RSS.
- Sampling-limited RAM is excluded from the index.
- Commands with non-zero measured exits continue running but are excluded from rankings.
- If none of the selected dimensions is usable, reports mark the balanced ranking unavailable.
- Ctrl+C keeps completed comparison rounds.
- Command output is discarded unless
-show-outputis set. - Native executables run through the inspected artifact and are identity/hash-checked after measurement.
- Scripts preserve their original invocation path so
$0-relative behavior is unchanged.
Saved reports are staged before publication and receive a numeric suffix rather than overwriting an existing report with the same timestamp.
- Linux reads
/procand measures every member of the command's process group, including descendants reparented while the benchmark is running. - macOS uses cgo with
proc_listpgrppids,proc_pidinfo, andproc_pid_rusage. - macOS physical footprint estimates memory pressure charged to each process.
- Physical-footprint validity is tracked per run; unavailable samples are not treated as zero.
- Tree RSS can double-count shared pages.
- Sampled peaks can miss activity shorter than the interval.
- macOS does not report file descriptor counts.
- For a simple external
-ccommand, disk footprint describes its leading executable; shell builtins describe the shell itself. - Disk-backed
@rpath,@loader_path, and@executable_pathlibraries are resolved recursively. - macOS dyld shared-cache libraries are listed but excluded from byte totals.
- Shared-cache libraries have no standalone size attributable to one command.
- Runtime plugins and executables launched by children are not included.
Commands that daemonize or escape their process group are unsupported.