Help text

This commit is contained in:
David Peter committed 2026-10-06 15:43:19 +02:00
1 parent 15108de79e
commit 4f62157cc9
2 files changed
+39 -91

No files matched your search

+22 -11
View File
@@ -55,17 +55,28 @@ fn build_command() -> Command {
.long("metrics")
.value_name("PRESET|METRIC[:UNIT],…")
.default_value("default")
.help("Metrics to display, in order. The first is used for non-JSON exports. \
Compare all commands with the first command. Presets: default (wall-clock \
time and peak RSS; wall-clock time only on Windows), time (wall-clock, total CPU, \
user, and system time), all (all available metrics, skipping unavailable \
measurements). All presets use automatic \
units with wall-clock time first; use a preset on its own. Metrics: time_wall_clock, \
time_cpu (user + system), time_user, time_system, memory_peak_resident, cpu_cycles, instructions, \
cache_references, cache_misses, branch_misses. Optional units: ns/us/ms/s/min/h \
for time, B/kB/MB/GB/TB/KiB/MiB/GiB/TiB for memory, count/k/M/B for counters \
(k = thousand, M = million, B = billion). Example: \
--metrics memory_peak_resident:MiB,time_wall_clock:ms,instructions:B."),
.hide_default_value(true)
.help("Performance metrics to measure, in order.\n\n\
This is either a preset name, or a comma-separated list of metrics with optional units. \
The first metric is used for non-JSON exports, \
JSON always includes all collected metrics.\n\n\
Presets (use one on its own):\n \
default Wall-clock time and peak RSS\n \
time Wall-clock, CPU, user, and system time\n \
all All available metrics\n\n\
Presets use automatic units.\n\n\
Metrics and optional units:\n \
Time: time_wall_clock, time_cpu, time_user, time_system\n \
Units: ns, us, ms, s, min, h\n \
Memory: memory_peak_resident\n \
Units: B, kB, MB, GB, TB, KiB, MiB, GiB, TiB\n \
Counters: cpu_cycles, instructions, cache_references,\n \
cache_misses, branch_misses\n \
Units: count, k (thousand), M (million), B (billion)\n\n\
Examples:\n \
--metrics time_cpu,instructions\n \
--metrics memory_peak_resident:MiB,time_wall_clock:ms\n \
--metrics time"),
)
.arg(
Arg::new("warmup")
+17 -80
View File
@@ -37,51 +37,11 @@ fn json_snapshot_settings() -> insta::Settings {
#[test]
fn runs_successfully() {
let output = hyperfine()
.arg("--metrics=default")
hyperfine()
.arg("--runs=2")
.arg("echo dummy benchmark")
.output()
.unwrap();
assert!(output.status.success(), "{:?}", output);
let stdout = String::from_utf8(output.stdout).unwrap();
assert!(stdout.contains("Wall Time"));
assert!(!stdout.contains("User time"));
assert!(!stdout.contains("System time"));
assert_eq!(stdout.contains("Memory"), !cfg!(windows));
assert!(!stdout.contains("Change"));
assert!(!stdout.contains("Outliers"));
}
#[test]
fn metric_presets_select_available_metrics() {
for preset in ["time", "all"] {
let output = hyperfine_debug()
.arg(format!("--metrics={preset}"))
.args(["--style=basic", "--runs=2", "sleep 1", "sleep 2"])
.output()
.unwrap();
assert!(output.status.success(), "{:?}", output);
let stdout = String::from_utf8(output.stdout).unwrap();
assert_eq!(stdout.matches("Wall Time").count(), 2);
assert_eq!(stdout.matches("CPU time").count(), 2);
assert_eq!(stdout.matches("User time").count(), 2);
assert_eq!(stdout.matches("System time").count(), 2);
assert_eq!(stdout.contains("Memory"), preset == "all" && !cfg!(windows));
assert!(!stdout.contains("CPU cycles"));
assert!(!stdout.contains("Instructions"));
assert!(!stdout.contains("Change vs #1"));
assert!(stdout.contains("+100.0%"));
}
// Explicit selections still require the metric, unlike the `all` preset.
hyperfine_debug()
.args(["--metrics=instructions", "--runs=1", "sleep 1"])
.assert()
.failure()
.stderr(predicate::str::contains(
"Metric 'instructions' is unavailable",
));
.success();
}
#[test]
@@ -151,13 +111,23 @@ fn fails_with_zero_runs() {
#[test]
fn min_runs_of_one_still_performs_one_run() {
hyperfine_debug()
let _settings = snapshot_settings().bind_to_scope();
assert_cmd_snapshot!(hyperfine_debug()
.arg("--style=basic")
.arg("--metrics=time_wall_clock")
.arg("--min-runs=1")
.arg("--warmup=0")
.arg("sleep 4")
.assert()
.success()
.stdout(predicate::str::contains("Benchmark 1: sleep 4 (1 run)"));
.arg("sleep 4"), @"
success: true
exit_code: 0
----- stdout -----
Benchmark 1: sleep 4 (1 run)
Value
Wall Time 4.000 s
----- stderr -----
");
}
#[test]
@@ -848,39 +818,6 @@ fn comparison_and_markup_identify_first_command_as_reference() {
assert!(row.ends_with("| N/A | |"), "{}", row);
}
#[test]
fn shows_name_of_first_command() {
let _settings = snapshot_settings().bind_to_scope();
assert_cmd_snapshot!(hyperfine_debug()
.arg("--metrics=time_wall_clock,memory_peak_resident")
.arg("--style=basic")
.arg("sleep 2.0")
.arg("--command-name=refabc123")
.arg("sleep 1.0")
.arg("sleep 3.0"), @"
success: true
exit_code: 0
----- stdout -----
Benchmark 1: refabc123 (10 runs)
mean ± σ min … max
Wall Time 2.000 s ± 0.000 s 2.000 s … 2.000 s
Memory 0.0 B ± 0.0 B 0.0 B … 0.0 B
Benchmark 2: sleep 1.0 (10 runs)
mean ± σ min … max
Wall Time 1.000 s ± 0.000 s 1.000 s … 1.000 s -50.0% (2.0x faster)
Memory 0.0 B ± 0.0 B 0.0 B … 0.0 B N/A
Benchmark 3: sleep 3.0 (10 runs)
mean ± σ min … max
Wall Time 3.000 s ± 0.000 s 3.000 s … 3.000 s +50.0% (1.5x slower)
Memory 0.0 B ± 0.0 B 0.0 B … 0.0 B N/A
----- stderr -----
");
}
#[test]
fn performs_all_benchmarks_in_parameter_scan() {
let _settings = snapshot_settings().bind_to_scope();