Skip to content

Repository files navigation

snailrace

snailrace benchmarks commands on Linux and macOS. It measures time, CPU, memory, process structure, and static disk footprint.

snailrace usage animation

Install

Homebrew (macOS / Linux)

brew install shellcell/tap/snailrace

Linux packages (apt / dnf / apk)

Enable 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 # Alpine

Arch (AUR)

With an AUR helper (e.g. paru or yay):

paru -S snailrace # builds from source
paru -S snailrace-bin # prebuilt binary

Or manually:

git clone https://aur.archlinux.org/snailrace.git # or snailrace-bin.gitcd snailrace && makepkg -si

Go

go install github.com/shellcell/snailrace/cmd/snailrace@latest # Go 1.22+

Prebuilt binaries

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.

Build

Requires Go 1.22+. macOS also requires a C compiler for the cgo libproc sampler.

make build

Examples

Benchmark one command:

./snailrace -n 20 -warmups 3 -- gzip -k sample.txt

Compare 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 --flag

Use -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

Options

OptionPurpose
-c, -commandShell command; repeat to compare
-labelCommand display label
-prepareOne-time setup command
-n, -runsMeasured runs; default 10
-warmupsWarmup runs; default 1
-intervalSampling interval; default 10 ms
-indexIndex dimensions: time,cpu,ram,disk
-baseline1-based baseline; 0 selects the winner
-f, -formatSaved format; default html
-o, -outputReport directory; default current directory
-no-saveDo not save report files
-verboseFull statistical tables on stdout
-show-outputForward command output to stderr
tuiRun inside a pseudo-terminal
-d, -durationFixed TUI duration
-width, -heightTUI geometry

Metrics

GroupMetrics
TimeWall time
CPUUser, system, total, average utilization
MemoryMean/peak tree RSS, OS max RSS, peak virtual memory
macOS memoryPeak aggregate physical footprint
StructurePeak processes, threads, file descriptors where available
DiskExecutable 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.

Method

  • 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-output is 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.

Platform Notes

  • Linux reads /proc and 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, and proc_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.

Disk Footprint

  • For a simple external -c command, disk footprint describes its leading executable; shell builtins describe the shell itself.
  • Disk-backed @rpath, @loader_path, and @executable_path libraries 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.

Releases

Packages

Contributors

Languages