默认直接执行命令不经过 shell,管道、重定向、通配符需加 -S 才生效;用 cargo 从源码安装需 Rust 1.97 或更新版本;冷缓存测试需先 sudo -v 获取权限才能执行清缓存命令
apt install hyperfineREADME 未说明硬件要求,工具跨平台,可在 Linux、macOS、Windows 等系统运行
命令行基准测试工具,多次运行统计对比任意 shell 命令的耗时与性能指标
命令行基准测试工具,能对任意 shell 命令做多次运行统计,自动给出耗时分布和置信区间,方便比较不同实现的性能差异。
核心能力
- 多次运行做统计分析并自动估算运行次数
- 支持预热运行与每次运行前清缓存命令
- 支持参数扫描与参数列表做参数化基准
- 可导出 CSV、JSON、Markdown、AsciiDoc 结果
- 统计离群值检测,识别外部程序与缓存干扰
容易踩的坑
- v2.0.0最新正式版2026-10-07 · 2026-10-07 21:13 UTC
See the breaking changes below when migrating from hyperfine 1.x.
Features
-
Add support for alternative performance metrics (peak memory usage, instructions, CPU cycles, cache misses, branch misses, ...). By default, hyperfine will now display wall-clock time and peak memory usage, but users can use the new
--metricsoption to select different performance metrics. The terminal output now shows an overview of all selected performance metrics (see here for a run with more metrics enabled). -
Add
--envto set environment variables even without an intermediate shell (which is the new default behavior, see below). For example:# Parameterized benchmark, comparing different thread counts: hyperfine -P threads 1 8 --env 'OMP_NUM_THREADS={threads}' 'my_command' -
The plotting and analysis scripts now support different metrics as well, see #981 and #984 (@sharkdp).
Breaking changes
-
Benchmarked commands are now executed directly by default, without an intermediate shell (
--shell=none). Use-S(an alias for--shell=default) to restore the previous behavior (shon Unix,cmd.exeon Windows), or select a shell with--shell <SHELL>. See the rationale for this change. -
Always run
--setup,--prepare,--conclude, and--cleanupcommands in a shell, even when using--shell=none, see #990 (@sharkdp). -
The JSON format for
--export-jsonhas changed (schema version 2). The new format now includes metadata, per-run measurements, and statistical summaries for all measured quantities, see #790 (@sharkdp). Code that reads those exported JSON files must be updated. For example,results[i].meanis nowresults[i].summary.time_wall_clock.mean, andresults[i].timesis replaced byresults[i].measurements[j].time_wall_clock.value. The new structure looks like this:{ "schema_version": 2, "primary_metric": "time_wall_clock", "metadata": { "hyperfine_version": "2.0.0", "start_time": "2026-10-06T12:00:00Z", "platform": {"os": "Linux", "architecture": "x86_64"} }, "results": [ { "command": "sleep 1", # Actual command after parameter substitution "name": "wait 1s", # Optional custom or automatically generated name "parameters": {"duration": {"value": "1"}}, # For parametrized runs "environment": {"OMP_NUM_THREADS": "8"}, # Only present with --env overrides "measurements": [ # One entry per run, excluding warmups { "time_wall_clock": {"value": 1.0, "unit": "second"}, "time_cpu": {"value": 0.0, "unit": "second"}, "time_user": {"value": 0.0, "unit": "second"}, "time_system": {"value": 0.0, "unit": "second"}, "memory_peak_resident": {"value": 1048576.0, "unit": "byte"}, "cpu_cycles": {"value": 5000000}, # Hardware counters, when available "instructions": {"value": 10000000}, "exit_code": 0 }, ... # Further runs omitted ], "summary": { "time_wall_clock": { "unit": "second", "count": 30, "mean": 1.0, "stddev": 0.0, "median": 1.0, "min": 1.0, "max": 1.0 }
-
- v2.0.0-alpha.2pre-release2026-10-07 · 2026-10-07 10:36 UTC
查看更新说明
Changes
- Always run
--setup,--prepare,--conclude, and--cleanupcommands in a shell, even when benchmarked commands run directly. Improve error messages for these commands, see #990 (@sharkdp). - Require an explicit shell choice for commands containing unquoted, standalone shell operators such as
&&or>: use-Sto interpret shell syntax or-Nto pass operators as literal arguments (@sharkdp). - Use a compact output layout on narrow terminals (@sharkdp).
- Make plotting and analysis scripts runnable directly from GitHub with
uvx --from 'git+https://github.com/sharkdp/hyperfine' <script>(@sharkdp).
- Always run
- v2.0.0-alpha.1pre-release2026-10-06 · 2026-10-06 14:06 UTC
查看更新说明
This is the first alpha release of hyperfine 2.0. Command-line options and export formats may change before the stable release. See the breaking changes below when migrating from hyperfine 1.x.
Features
- Add support for alternative performance metrics (peak memory usage, CPU cycles, instructions, cache misses, branch misses, ...). By default, hyperfine will now display wall-clock time and peak memory usage (wall-clock time only on Windows),
but users can use the new
--metricsoption to select different performance metrics. - The terminal output now shows an overview of all selected performance metrics, including relative changes.
- Python plotting and analysis scripts support the new JSON format and can select performance metrics with
--metric, see #981 and #984 (@sharkdp).
Breaking changes
-
Benchmarked commands are now executed directly by default, without an intermediate shell (
--shell=none). Use-S(an alias for--shell=default) to restore the previous behavior (shon Unix,cmd.exeon Windows), or select a shell with--shell <SHELL>. -
The JSON format for
--export-jsonhas changed (schema version 2). The new format now includes metadata, per-run measurements, and statistical summaries for all measured quantities, see #790 (@sharkdp). Code that reads those exported JSON files must be updated. For example,results[i].meanis nowresults[i].summary.time_wall_clock.mean, andresults[i].timesis replaced byresults[i].measurements[j].time_wall_clock.value. The new structure looks like this:{ "schema_version": 2, "primary_metric": "time_wall_clock", "metadata": { "hyperfine_version": "2.0.0-alpha.1", "start_time": "2026-10-06T12:00:00Z", "platform": {"os": "Linux", "architecture": "x86_64"} }, "results": [ { "command": "sleep 1", # Actual command after parameter substitution "name": "wait 1s", # Optional custom name, separate from the command "parameters": {"duration": {"value": "1"}}, # Values are now objects "measurements": [ # One entry per run, excluding warmups { "time_wall_clock": {"value": 1.0, "unit": "second"}, "time_user": {"value": 0.0, "unit": "second"}, "time_system": {"value": 0.0, "unit": "second"}, "memory_peak_resident": {"value": 1048576.0, "unit": "byte"}, "exit_code": 0 }, ... # Further runs omitted ], "summary": { "time_wall_clock": { "unit": "second", "count": 2, "mean": 1.0, "stddev": 0.0, "median": 1.0, "min": 1.0, "max": 1.0 } # Other metrics have the same summary structure. } } ] }Times are always exported in seconds and memory in bytes.
-
--time-unit/-uhas been removed. Units can now be selected using the--metrics METRIC[:UNIT],…option, e.g.--metrics time_wall_clock:ms,memory_peak_resident:MiB. -
--sorthas been removed. It complicated hyperfine significantly and doesn't make too much sense with the new output format. -
--referenceand--reference-namehave been removed (for now). The first command is always considered as the reference command. -
The format of Markdown, AsciiDoc, org-mode and CSV exports has also been changed. These formats contain only the primary metric (the first metric selected by
--metrics). CSV now includes columns with the name and the unit of the primary metric.
- Add support for alternative performance metrics (peak memory usage, CPU cycles, instructions, cache misses, branch misses, ...). By default, hyperfine will now display wall-clock time and peak memory usage (wall-clock time only on Windows),
but users can use the new
- v1.21.02026-10-05 · 2026-10-05 14:11 UTC
查看更新说明
Features
- Add support for minutes and hours in
--time-unit, as well as short and plural aliases such asms,seconds, andmin, see #960 (@sharkdp) - Expose
$HYPERFINE_ITERATIONto--prepareand--concludecommands, see #781 and #807 (@willcl-ark) - Show elapsed time during the initial benchmark run, see #416 and #581 (@devonhollowood)
- Add colors to
--helpoutput, see #841 (@starsep)
Changes
- With
--parameter-scanor--parameter-list,--referencenow selects an existing benchmark by its full displayed name instead of running a separate reference command. The name must match exactly one benchmark; use--command-nameinstead of--reference-namein this mode, see #847 and #979 (@sharkdp) - Format times in CSV exports with six decimal places, see #966 and #972 (@sharkdp)
- Update dependencies and raise the minimum supported Rust version to 1.97, see #934 (@sharkdp)
Bugfixes
- Make Markdown, AsciiDoc, and Org-mode exports compare against the specified reference, and label faster and slower results in command-sorted comparisons with
--reference, see #811 and #979 (@sharkdp) - Reject zero values for
--runs,--min-runs, and--max-runsinstead of allowing invalid run counts, see #923 (@VXNCXNX, @sharkdp) - Reject negative parameter-scan steps before expanding ranges, avoiding hangs and excessive memory use, see #951 (@Likio3000)
- Preserve existing export files when command options are invalid, see #950 (@Likio3000)
- Truncate export files when rewriting results to avoid leaving trailing bytes, see #970 (@sharkdp)
- Preserve backticks in command names in Markdown exports, see #947 (@Likio3000)
- Handle broken output pipes gracefully instead of panicking, see #932 (@Mathjk)
- Collect peak memory usage separately for each command on Unix, so commands no longer inherit the peak memory usage of earlier commands, see #965 (@sharkdp)
- Preserve 100-nanosecond precision in Windows CPU times, see #964 (@sharkdp)
- Python scripts: Correct the interpretation of Welch's t-test results, see #943 (@sharkdp)
Other
- Build binaries for Windows ARM64 and Linux ARM64 musl, see #922 and #924 (@meop)
- Refactor measurement, statistics, and formatting code to use typed quantities, see #954, #958, #961, #967, #969, #971, and #976 (@sharkdp)
- Improve documentation and examples, including comparisons across Git branches, iteration variables, reference commands, and selective failure handling, see #899, #900, #929, and #940 (@xfocus3, @ded-furby, @Likio3000, @sharkdp)
- Add support for minutes and hours in
- v1.20.02025-11-18 · 2025-11-18 08:38 UTC
查看更新说明
v1.20.0
Features
- Add
--reference-nameoption to give a meaningful name to the reference command, see #808 (@niklasdewally) - The
--ignore-failureoption now supports a comma-separated list of exit codes to ignore (e.g.,--ignore-failure=1,2), see #836 (@sharkdp) - Python scripts: Add
--time-unitoption toadvanced_statistics.py(@sharkdp) - Python scripts: Add new
plot_benchmarks.pyscript for plotting collections of benchmarks, see #806 (@marxin)
Bugfixes
- Fix bug where naming individual commands with parameter scan was not working correctly, see #794 (@teofr)
Other
- Restrict
cattests to Unix environments, see #776 and #777 (@ritvikos)
- Add
用户点评
登录用户的真实使用记录,可按版本和硬件筛选还没有人点评。第一个说出真实体验的人最有价值。
hyperfine
A command-line benchmarking tool.
(hyperfine in action, benchmarking mypy and ty)
Features
- Statistical analysis across multiple runs.
- Support for various performance metrics and hardware counters.
- Support for arbitrary shell commands.
- Constant feedback about the benchmark progress and current estimates.
- Warmup runs can be executed before the actual benchmark.
- Cache-clearing commands can be set up before each benchmark run.
- Statistical outlier detection to detect interference from other programs and caching effects.
- Export results to various formats: CSV, JSON, Markdown, AsciiDoc.
- Parameterized benchmarks (e.g. vary the number of threads).
- Cross-platform
Usage
Basic benchmarks
To run a benchmark, you can simply call hyperfine <command>.... Each argument is an executable
and its arguments. Commands run directly by default; use -S for shell syntax such as
pipes, redirections, and wildcards. For example:
hyperfine 'sleep 0.3'
Hyperfine will automatically determine the number of runs to perform for each command. By default,
it will perform at least 10 benchmarking runs and estimate a run count targeting roughly
3 seconds, including shell overhead and preparation and conclusion commands. To set an exact
number of runs, you can use the -r/--runs option:
hyperfine --runs 5 'sleep 0.3'
If you want to compare different programs, you can pass multiple commands:
hyperfine 'hexdump file' 'xxd file'
Commands run and appear in input order. The first command is the reference for all comparisons; each subsequent result shows its change from that reference.
Warmup runs and preparation commands
For programs that perform a lot of disk I/O, the benchmarking results can be heavily influenced by disk caches and whether they are cold or warm.
If you want to run the benchmark on a warm cache, you can use the -w/--warmup option to
perform a certain number of program executions before the actual benchmark:
hyperfine -S --warmup 3 'grep -R TODO *'
Conversely, if you want to run the benchmark for a cold cache, you can use the -p/--prepare
option to run a special command before each benchmark run. For example, to clear Linux filesystem caches,
you can run
sync; echo 3 | sudo tee /proc/sys/vm/drop_caches
To use this specific command with hyperfine, call sudo -v to temporarily gain sudo permissions
and then call:
hyperfine -S --prepare 'sync; echo 3 | sudo tee /proc/sys/vm/drop_caches' 'grep -R TODO *'
Parameterized benchmarks
If you want to run a series of benchmarks where a single parameter is varied (say, the number of
threads), you can use the -P/--parameter-scan option and call:
hyperfine --prepare 'make clean' --parameter-scan num_threads 1 12 'make -j {num_threads}'
This also works with decimal numbers. The -D/--parameter-step-size option can be used
to control the step size:
hyperfine --parameter-scan delay 0.3 0.7 -D 0.2 'sleep {delay}'
This runs sleep 0.3, sleep 0.5 and sleep 0.7.
For non-numeric parameters, you can also supply a list of values with the -L/--parameter-list
option:
hyperfine -L compiler g++,clang++ '{compiler} -O2 main.cpp'
A common use case is comparing the same command across multiple Git branches. Use --setup
to switch branches once before each set of benchmark runs, so the branch switch is not part of
the measured command:
hyperfine \
--parameter-list branch main,performance-improvements \
--setup 'git switch {branch}' \
'python main.py'
If you need a unique value for each individual run of a benchmark command, hyperfine also exposes
the zero-based $HYPERFINE_ITERATION environment variable inside the benchmarked command itself:
hyperfine -S 'my-command > output-${HYPERFINE_ITERATION}.log'
Intermediate shell
By default, benchmarked commands, including warmup runs, are executed directly, without an intermediate shell (--shell=none).
Arguments are split using shell-like quoting, so quoted arguments containing spaces are supported.
Shell syntax such as pipes, redirections, environment-variable expansion, *, and ~ is not interpreted.
This avoids shell startup overhead and the noise from correcting for it, especially for fast commands
(< 5 ms).
Commands containing unquoted, standalone shell operators such as && or > require an explicit
choice: use -S / --shell=default to interpret shell syntax, or -N / --shell=none to pass
the operators as literal arguments.
To enable shell syntax, use -S (an alias for --shell=default). This selects sh
on Unix (resolved through PATH) or cmd.exe on Windows:
hyperfine -S 'sleep 0.1 && echo done'
You can also select a specific shell with --shell <SHELL>:
hyperfine --shell zsh 'for i in {1..10000}; do echo test; done'
The --setup, --prepare, --conclude, and --cleanup commands always run through a shell.
They use the shell selected by --shell, or the platform shell (sh on Unix, cmd.exe on Windows)
when --shell is omitted or set to none.
When benchmarked commands use a shell, hyperfine corrects for the shell spawning time. It runs the shell with an empty command multiple times to measure its startup time, then subtracts this time from each time measurement.
Shell functions
If you are using bash, you can export shell functions to directly benchmark them with hyperfine:
my_function() { sleep 1; }
export -f my_function
hyperfine --shell=bash my_function
Otherwise, inline the function into the benchmarked command:
hyperfine -S 'my_function() { sleep 1; }; my_function'
Environment variables
Use --env to set environment variables for benchmark commands and their respective setup, prepare, conclude,
and cleanup commands. Assignments are space-separated and support shell-style quoting,
but no shell expansion:
hyperfine --env 'OMP_NUM_THREADS=8 CFLAGS="-O3 -march=native"' 'my_command'
Specify once for all commands or once per benchmark command:
hyperfine \
--env 'OMP_NUM_THREADS=8' './benchmark-cpp' \
--env 'RAYON_NUM_THREADS=8' './benchmark-rust'
Use an empty --env='' for no overrides. Values can contain parameter placeholders.
For example, the following benchmarks my_command with OMP_NUM_THREADS ranging from 1 to 8:
hyperfine -P threads 1 8 --env 'OMP_NUM_THREADS={threads}' 'my_command'
Choosing metrics and units
By default, hyperfine displays wall-clock time and memory usage
(time_wall_clock,memory_peak_resident). Use --metrics with a
comma-separated list to select a different set of metrics. Each
metric can have an optional unit after it:
hyperfine \
--metrics memory_peak_resident:MiB,time_wall_clock:ms,instructions \
'./baseline' './candidate'
The following metrics are available:
-
time_wall_clock: Time from start to finish, including time spent waiting, in seconds. -
time_user: CPU time spent executing application and library code in user mode, summed across threads, in seconds.- Linux/macOS: Includes child-process time when parents wait for their children to finish.
- Windows: Includes the command and its child processes.
-
time_system: CPU time spent executing kernel code on the program's behalf, for example to read files, summed across threads, in seconds.- Linux/macOS: Includes child-process time when parents wait for their children to finish.
- Windows: Includes the command and its child processes.
-
time_cpu: Total CPU time, calculated astime_user + time_systemfor each run, in seconds. It excludes time spent sleeping or waiting without executing. CPU time is summed across threads, so it can exceed wall-clock time: four threads running on four cores for one second can consume roughly four CPU-seconds. -
memory_peak_resident: Peak memory held in physical RAM, in bytes.- Linux/macOS: Peak resident set size (RSS). This is the largest per-process peak among the command and child processes (whose usage is collected when their parents wait for them), not the simultaneous total memory of the full process tree. On Linux, measuring commands with a very small peak RSS (below the peak inherited from hyperfine at startup, which can be a few MiB) will currently result in that inherited value being reported instead.
- Windows: Currently not supported.
-
cpu_cycles: CPU cycles consumed.- Linux: Includes threads and child processes, but excludes kernel and hypervisor execution.
- macOS: Includes the process's threads and kernel execution, but excludes child processes.
- Windows: Currently not supported.
-
instructions: Completed CPU instructions.- Linux/macOS: Same scope as
cpu_cycles. - Windows: Currently not supported.
- Linux/macOS: Same scope as
-
cache_references: Cache accesses counted by the CPU's generic cache event.- Linux: Same scope as
cpu_cycles. Cache-event definitions depend on the CPU. - macOS/Windows: Currently not supported.
- Linux: Same scope as
-
cache_misses: Cache misses.- Linux: Same scope as
cpu_cycles. Cache-event definitions depend on the CPU. - macOS/Windows: Currently not supported.
- Linux: Same scope as
-
branch_misses: Mispredicted branches.- Linux: Same scope as
cpu_cycles. - macOS/Windows: Currently not supported.
- Linux: Same scope as
Note that hardware counters are not available when a shell is enabled (--shell=..).
Time measurements support units ns, us, ms, s, min, and h. Memory measurements
support B, kB, MB, GB, TB, KiB, MiB, GiB, and TiB. Hardware counters
support count (1), k (thousand), M (million), and B (billion).
You can also use a preset to select a group of metrics:
| Preset | Metrics |
|---|---|
--metrics=default | time_wall_clock,memory_peak_resident |
--metrics=time | time_wall_clock,time_cpu,time_user,time_system |
--metrics=all | All available metrics |
Exporting results
Hyperfine can export results to CSV, JSON, Markdown, AsciiDoc, and org-mode. CSV exports all
selected metrics, while Markdown, AsciiDoc, and org-mode contain only the primary metric,
which is the first metric selected by --metrics.
Markdown
You can use the --export-markdown <file> option to create tables like the following:
| Command | Mean Wall Time [s] | Change | Factor |
|---|---|---|---|
find . -iregex '.*[0-9]\.jpg$' | 2.275 ± 0.046 | ||
find . -iname '*[0-9].jpg' | 1.427 ± 0.026 | -37.3% | (1.6x faster) |
fd -HI '.*[0-9]\.jpg$' | 0.232 ± 0.002 | -89.8% | (9.8x faster) |
JSON
The JSON export includes all available metrics listed in Choosing metrics and units for each measured run (excluding warmup runs).
The JSON output is useful if you want to analyze the benchmark results in more detail. The
scripts/ folder includes a lot
of helpful Python programs to further analyze benchmark results and create helpful
visualizations, like a histogram of runtimes or a whisker plot to compare
multiple benchmarks.
For example, these two commands create the following plots:
uvx --from 'git+https://github.com/sharkdp/hyperfine' \
plot_histogram results.json
uvx --from 'git+https://github.com/sharkdp/hyperfine' \
plot_whisker results.json
![]() | ![]() |
|---|
CSV
Use --export-csv <file> to export one row per command. Each metric selected by --metrics
contributes a group of columns, in selection order: <metric>_unit, <metric>_mean,
<metric>_stddev, <metric>_median, <metric>_min, and <metric>_max.
CSV uses explicitly selected units, or base units (seconds, bytes, or counts) when omitted.
Detailed benchmark flowchart
The following chart explains the execution order of various benchmark runs when using options
like --warmup, --prepare <cmd>, --setup <cmd> or --cleanup <cmd>:

Installation
On Ubuntu
On Ubuntu, hyperfine can be installed from the official repositories:
apt install hyperfine
Alternatively, for the latest version, you can download the appropriate .deb package from the Release page and install it via dpkg:
wget https://github.com/sharkdp/hyperfine/releases/download/v2.0.0/hyperfine_2.0.0_amd64.deb
sudo dpkg -i hyperfine_2.0.0_amd64.deb
On Fedora
On Fedora, hyperfine can be installed from the official repositories:
dnf install hyperfine
On Alpine Linux
On Alpine Linux, hyperfine can be installed from the official repositories:
apk add hyperfine
On Arch Linux
On Arch Linux, hyperfine can be installed from the official repositories:
pacman -S hyperfine
On Debian Linux
On Debian Linux, hyperfine can be installed from the official repositories:
apt install hyperfine
On Exherbo Linux
On Exherbo Linux, hyperfine can be installed from the rust repositories:
cave resolve -x repository/rust
cave resolve -x hyperfine
On NixOS
On NixOS, hyperfine can be installed from the official repositories:
nix-env -i hyperfine
On Flox
On Flox, hyperfine can be installed as follows.
flox install hyperfine
Hyperfine's version in Flox follows that of Nix.
On openSUSE
On openSUSE, hyperfine can be installed from the official repositories:
zypper install hyperfine
On Void Linux
Hyperfine can be installed via xbps
xbps-install -S hyperfine
On macOS
Hyperfine can be installed via Homebrew:
brew install hyperfine
Or you can install using MacPorts:
sudo port selfupdate
sudo port install hyperfine
On FreeBSD
Hyperfine can be installed via pkg:
pkg install hyperfine
On OpenBSD
doas pkg_add hyperfine
On Windows
Hyperfine can be installed via Chocolatey, Scoop, or Winget:
choco install hyperfine
scoop install hyperfine
winget install hyperfine
With conda
Hyperfine can be installed via conda from the conda-forge channel:
conda install -c conda-forge hyperfine
With cargo (Linux, macOS, Windows)
Hyperfine can be installed from source via cargo:
cargo install --locked hyperfine
Make sure that you use Rust 1.97 or newer.
From binaries (Linux, macOS, Windows)
Download the corresponding archive from the Release page.
Alternative tools
Hyperfine is inspired by bench.
Integration with other tools
Chronologer is a tool that uses hyperfine to
visualize changes in benchmark timings across your Git history.
Bencher is a continuous benchmarking tool that supports hyperfine to
track benchmarks and catch performance regressions in CI.
Drop hyperfine JSON outputs onto the Venz chart to visualize the results, and manage hyperfine configurations.
Make sure to check out the scripts folder
in this repository for a set of tools to work with hyperfine benchmark results.
Origin of the name
The name hyperfine was chosen in reference to the hyperfine levels of caesium 133 which play a crucial role in the definition of our base unit of time — the second.
Citing hyperfine
Thank you for considering citing hyperfine in your research work. Please see the information in the sidebar on how to properly cite hyperfine.
License
hyperfine is dual-licensed under the terms of the MIT License and the Apache License 2.0.
See the LICENSE-APACHE and LICENSE-MIT files for details.

