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 } # Other metrics have the same summary structure. } } ] }Times are always exported in seconds and memory in bytes. Hardware counters and their summaries have no
unitfield. Unavailable memory measurements and hardware counters are omitted; other available counters may also be included.stddevisnullfor a single run. -
--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. Invocations using--referencenow show migration guidance to put the reference command first. -
The format of Markdown, AsciiDoc and org-mode, and CSV exports has also been changed. Markdown, AsciiDoc, and org-mode contain only the primary metric (the first metric selected by
--metrics). CSV exports all selected metrics side by side.