From 4f62157cc947fbf7a2d53fd0e5e6f3d04cece1ba Mon Sep 17 00:00:00 2001 From: David Peter Date: Tue, 6 Oct 2026 15:43:19 +0200 Subject: [PATCH] Help text --- src/cli.rs | 33 ++++++++----- tests/integration_tests.rs | 97 +++++++------------------------------- 2 files changed, 39 insertions(+), 91 deletions(-) diff --git a/src/cli.rs b/src/cli.rs index fb8ca3e..712aa0b 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -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") diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index 307a82a..2950d50 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -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();