CLI tool
sharkdp/hyperfine avatar
sharkdp/hyperfine

hyperfine: benchmarking shell commands from the terminal

A command-line benchmarking tool

28,917 stars511 forksRustApache-2.0

At a glance

What is it?
hyperfine is a Rust command-line benchmarking tool that runs shell commands repeatedly, corrects for shell startup time and exports the timings. It suits engineers comparing two commands on one machine, not people looking for a portable benchmark suite.
Who is it for?
Adopt hyperfine if you are comparing two or three commands on one machine and want the shell startup overhead subtracted and the numbers exported as JSON or Markdown. Do not adopt it if you need a reproducible benchmark suite that runs unchanged across machines, or if you cannot control the caches on the machine you are measuring.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 152 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 28, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

What hyperfine measures, and what it refuses to measure

hyperfine wraps a shell command, runs it many times, and reports the distribution of wall-clock times. The README describes it as "A command-line benchmarking tool" and the Cargo.toml describes it as "A command-line benchmarking tool" with the category command-line-utilities. That is the whole scope. It does not profile a process, does not read perf counters, and does not instrument your code. If you want to know which function inside a binary is slow, hyperfine is the wrong instrument; it only tells you that one command line took longer than another.

The intended user is someone at a terminal who has two candidate commands and a question like "is fd actually faster than find here". The README's own demo benchmarks fd against find. The audience is narrow on purpose: developers, packagers and anyone writing a shell script who needs a defensible number rather than a stopwatch and a feeling.

One design decision matters more than the feature list. hyperfine always corrects for shell spawning time. According to the README, it runs a calibration procedure that executes the shell with an empty command several times, measures the startup time, and subtracts that from the total. That is the right call for a command that takes a second. It is the wrong call for a command that takes two milliseconds, which is exactly why the -N / --shell=none option exists: the README states it is helpful for very fast commands (under 5 ms) where the correction would produce a significant amount of noise, and warns that shell syntax like * or ~ cannot be used in that mode.

Run count, warmup and prepare: the three knobs that decide your result

By default hyperfine performs at least 10 benchmarking runs and measures for at least 3 seconds, per the README. Those two conditions interact: a fast command will be run far more than ten times to fill the three-second window, and a slow command will stop at ten runs even if that takes a minute. The -r / --runs flag overrides the count.

Cache state is the second knob and the one most often ignored. The README is explicit that for programs doing a lot of disk I/O the results can be heavily influenced by disk caches and whether they are cold or warm. Warmup runs (-w / --warmup) execute the program a number of times before timing begins. The opposite case uses -p / --prepare, which runs a command before each timing run; the README's Linux example drops the page cache with sync; echo 3 | sudo tee /proc/sys/vm/drop_caches, and it notes you should call sudo -v first to hold sudo permissions for the duration.

There is a real cost here that the feature list does not advertise. A cold-cache benchmark on Linux needs root, and it changes the state of the machine for everything else running on it. On a shared or containerized host you may not be able to do it at all, and a warm-cache number from that host is not comparable to a cold-cache number from another. The README does not document a way to verify that the cache was actually dropped between runs.

Installing hyperfine and running a first comparison

The README lists distribution packages for several Linux distributions and points at the release page for .deb files. On Ubuntu the package is in the official repositories, so apt install hyperfine is enough; the README notes that for the latest version you can download the .deb from the release page and install it with dpkg instead.

bash
apt install hyperfine

Fedora and Alpine have equivalent commands in the README, dnf install hyperfine and apk add hyperfine. Arch Linux is covered as well, and the README links a packaging status badge for other platforms. If your distribution is not listed there, the README does not give a cargo install line, so check the packaging status page before assuming a source build is documented.

A first real use is a two-command comparison. The README gives exactly this shape with hexdump and xxd:

bash
hyperfine 'hexdump file' 'xxd file'

You should see a progress display while the runs execute, then a summary table with mean, min, max and a relative column. The relative column is the useful part: it normalizes against the fastest command, so in the README's Markdown example fd appears as 1.00 and the two find variants as 9.79 and 6.14 times slower.

For a parameterized sweep, the -P / --parameter-scan flag substitutes a named placeholder. The README's example varies the thread count for make:

bash
hyperfine --prepare 'make clean' --parameter-scan num_threads 1 12 'make -j {num_threads}'

The --prepare here is doing real work: without it, the second and later runs would reuse build artifacts and the timings would be meaningless. Decimal parameters work too, with -D / --parameter-step-size controlling the increment; the README's example runs sleep 0.3, sleep 0.5 and sleep 0.7. For non-numeric values, -L / --parameter-list takes a comma-separated set, as in -L compiler gcc,clang '{compiler} -O2 main.cpp'.

Exporting results and the scripts/ folder

hyperfine writes its output to the terminal by default, but the README documents export options for CSV, JSON, Markdown and AsciiDoc, with the full list in the --help text. The Markdown export produces a table with Command, Mean, Min, Max and Relative columns, which is the format you would paste into a pull request or a design document.

The JSON export is the one worth knowing about even if you never open it by hand. The README states the JSON output is useful for analyzing results in more detail, and points at the scripts/ folder in the repository, which contains Python programs for further analysis and visualization, including a histogram of runtimes and a whisker plot comparing multiple benchmarks. Both images appear in the README's doc/ folder.

What the README does not say is what those scripts expect as input, or whether they are maintained alongside the CLI. The repository layout shows scripts/ and doc/ as top-level directories, and the Cargo.toml does not list them as part of the published crate, so treat the scripts as repository tooling rather than a supported interface. If your workflow depends on them, read them before you build a pipeline on top.

Where hyperfine gives you the wrong answer

The most common failure is benchmarking something that is not stable across runs. If your command hits the network, reads from a database, or depends on a JIT warmup curve, hyperfine will faithfully report a distribution that describes your environment rather than the command. The outlier detection the README lists as a feature will flag interference from other programs, but flagging is not fixing: a noisy machine produces a wide spread, and the mean of a wide spread is not a result you should quote.

The second failure is scope. hyperfine measures wall-clock time of a process tree. It does not separate user time from system time, does not report memory, and does not report I/O. A command that got faster because it now waits on a cache instead of computing will look better in hyperfine and may be worse in practice. Nothing in the README suggests hyperfine tries to detect that.

The third is portability of the number itself. The README's cross-platform claim is about the tool running on multiple platforms, not about results transferring between them. Shell startup correction, cache behavior and scheduler differences all vary by OS. A hyperfine number from a laptop is not evidence about a production server, and the README does not offer a way to make it one.

hyperfine against time, perf stat and hyperfine's own shell mode

The obvious alternative is the shell builtin time, or /usr/bin/time. The difference in approach is statistical: time gives you one number per invocation, and you do the repetition and averaging yourself. hyperfine does the repetition, reports a spread, and adds the shell startup correction. For a single slow command you do not need hyperfine; for a fast command where run-to-run variation is a large fraction of the total, the builtin tells you almost nothing.

A closer alternative for the same job is perf stat, which counts hardware and kernel events rather than wall-clock time. That is a different question. perf stat can tell you that a command executed fewer instructions or suffered fewer cache misses; hyperfine can only tell you it finished sooner. If your change is supposed to reduce work rather than latency, perf stat is the more informative tool. If you are choosing between two binaries that do the same job, hyperfine's relative column is the more direct answer.

There is also a comparison inside hyperfine itself: the default mode with an intermediate shell versus -N / --shell=none. The README notes the default shell is /bin/sh on Unix and cmd.exe on Windows, and that -S / --shell lets you pick another, for example --shell zsh. The -N mode skips the shell entirely and is aimed at commands under 5 ms, at the cost of losing globbing and tilde expansion. Choosing wrong in either direction is a real source of bad numbers: shell mode adds noise to a very fast command, and no-shell mode breaks a command that relies on shell syntax.

Maintenance, licence and the cost of upgrading

The repository is not archived. The last push was on 2026-04-30. Release cadence, from the release list, has been roughly annual in recent years: v1.18.0 on 2023-10-05, v1.19.0 on 2024-11-11, and v1.20.0 on 2025-11-18. That is a stable tool, not a fast-moving one, and the practical upgrade cost is low for the CLI surface: the documented flags are the same family across those releases.

The Cargo.toml sets rust-version = "1.88.0", which matters if you install by building from source rather than from a package. A distribution package will bundle its own build; a source build needs a recent toolchain. The crate declares edition = "2018" and a build.rs, which generates shell completions from clap at build time, so a source build pulls clap and clap_complete as build dependencies on top of the runtime dependencies.

Licensing is dual, and this is worth reading carefully before you vendor the code. Cargo.toml declares license = "MIT OR Apache-2.0", and the repository carries both LICENSE-MIT and LICENSE-APACHE at the top level. The dual grant means you pick one of the two when you redistribute; the two files are the ones that apply, not the single Apache-2.0 tag shown in some metadata. That is a redistribution question, not a usage question: running the binary as a tool does not engage either licence. If you embed hyperfine's source in your own product, read both files and decide which grant you are relying on. This is not legal advice.

Editorial conclusion

Adopt hyperfine if you are comparing two or three commands on one machine and want the shell startup overhead subtracted and the numbers exported as JSON or Markdown. Do not adopt it if you need a reproducible benchmark suite that runs unchanged across machines, or if you cannot control the caches on the machine you are measuring. Before trusting a result, verify the run count with -r, check whether the shell startup correction is the right trade-off for your command duration, and confirm whether you need --warmup or --prepare for your cache state. The repository is not archived; the last push was on 2026-04-30.

Frequently asked questions

How do I install hyperfine?

The README lists distribution packages for several Linux distributions, including apt install hyperfine on Ubuntu, dnf install hyperfine on Fedora and apk add hyperfine on Alpine Linux. For the latest version on Ubuntu you can download the .deb from the release page and install it with dpkg. The README links a packaging status badge for other platforms.

How do I use hyperfine to compare two commands?

Pass both commands as separate arguments, for example hyperfine 'hexdump file' 'xxd file'. hyperfine runs each command at least 10 times and for at least 3 seconds by default, then prints a table with mean, min, max and a relative column normalized against the fastest command.

What does hyperfine do about shell startup time?

The README states that hyperfine always corrects for shell spawning time using a calibration procedure that runs the shell with an empty command several times and subtracts the measured startup time from the total. For very fast commands under 5 ms, the README recommends -N or --shell=none, which skips the intermediate shell entirely but does not support shell syntax like * or ~.

Which formats can hyperfine export benchmark results to?

The README documents CSV, JSON, Markdown and AsciiDoc export, with the full option list in the --help text. The JSON output is intended for deeper analysis, and the repository's scripts/ folder contains Python programs that produce visualizations such as a histogram of runtimes and a whisker plot.

Can hyperfine benchmark a command on a cold disk cache?

Yes, using -p or --prepare to run a command before each timing run. The README's Linux example is sync; echo 3 | sudo tee /proc/sys/vm/drop_caches, and it advises calling sudo -v first to hold sudo permissions. The README does not document a way to confirm the cache was actually dropped.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. README
  4. Releases
  5. sharkdp/hyperfine on GitHub
For maintainers

Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/sharkdp-hyperfine.svg)](https://hysenlabs.com/projects/sharkdp-hyperfine)
Community notes

Community notes