From a947ba1d065fc316b6d14f13568ece35e59e7613 Mon Sep 17 00:00:00 2001 From: David Peter Date: Tue, 6 Oct 2026 15:09:25 +0200 Subject: [PATCH] Simplifications --- README.md | 10 ++-- src/export/asciidoc.rs | 11 +++- src/export/markup.rs | 16 +++--- src/export/tests.rs | 108 ++++++++++++++++------------------- src/metric.rs | 78 +++++++++++++++++++++---- src/output/report.rs | 16 ++++-- tests/integration_tests.rs | 114 ++++++++++++++++++++++--------------- 7 files changed, 218 insertions(+), 135 deletions(-) diff --git a/README.md b/README.md index c7824ef..f93fbb2 100644 --- a/README.md +++ b/README.md @@ -241,11 +241,11 @@ contain only the primary metric. You can use the `--export-markdown ` option to create tables like the following: -| Command | Mean Wall Time [s] | Min [s] | Max [s] | Change | -|:---|---:|---:|---:|---:| -| `find . -iregex '.*[0-9]\.jpg$'` | 2.275 ± 0.046 | 2.243 | 2.397 | | -| `find . -iname '*[0-9].jpg'` | 1.427 ± 0.026 | 1.405 | 1.468 | -37.3% | -| `fd -HI '.*[0-9]\.jpg$'` | 0.232 ± 0.002 | 0.230 | 0.236 | -89.8% (9.8x faster) | +| 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% | | +| `fd -HI '.*[0-9]\.jpg$'` | 0.232 ± 0.002 | -89.8% | (9.8x faster) | #### JSON diff --git a/src/export/asciidoc.rs b/src/export/asciidoc.rs index 70dfc18..ac6b18a 100644 --- a/src/export/asciidoc.rs +++ b/src/export/asciidoc.rs @@ -24,7 +24,16 @@ impl MarkupExporter for AsciidocExporter { } fn table_row(&self, cells: &[&str]) -> String { - format!("\n| {}\n", cells.join("\n| ")) + let mut row = String::from("\n"); + for cell in cells { + row.push('|'); + if !cell.is_empty() { + row.push(' '); + row.push_str(cell); + } + row.push('\n'); + } + row } fn table_divider(&self, _cell_aligmnents: &[Alignment]) -> String { diff --git a/src/export/markup.rs b/src/export/markup.rs index 3c3c0c3..338cecb 100644 --- a/src/export/markup.rs +++ b/src/export/markup.rs @@ -22,16 +22,14 @@ pub trait MarkupExporter { Alignment::Left, Alignment::Right, Alignment::Right, - Alignment::Right, - Alignment::Right, + Alignment::Left, ]; let mut table = self.table_header(&cells_alignment); table.push_str(&self.table_row(&[ "Command", &format!("Mean {} {notation}", primary.metric.label()), - &format!("Min {notation}"), - &format!("Max {notation}"), "Change", + "Factor", ])); table.push_str(&self.table_divider(&cells_alignment)); @@ -43,16 +41,20 @@ pub trait MarkupExporter { .map(|value| format!(" ± {}", unit.format_value(value))) .unwrap_or_default(); let change = if index == 0 { - "reference".to_owned() + String::new() } else { stats.format_change_from(&summaries[0]) }; + let factor = if index == 0 { + String::new() + } else { + stats.format_factor_from(&summaries[0], primary.metric) + }; table.push_str(&self.table_row(&[ &self.command(&command), &format!("{mean}{stddev}"), - &unit.format_value(stats.min), - &unit.format_value(stats.max), &change, + &factor, ])); } table.push_str(&self.table_footer(&cells_alignment)); diff --git a/src/export/tests.rs b/src/export/tests.rs index 676b830..651c8db 100644 --- a/src/export/tests.rs +++ b/src/export/tests.rs @@ -107,40 +107,37 @@ fn test_markup_export_auto_ms() { ]; insta::assert_snapshot!(get_output::(&results, None), @" - | Command | Mean Wall Time [ms] | Min [ms] | Max [ms] | Change | - |:---|---:|---:|---:|---:| - | `sleep 0.1` | 110.0 ± 26.5 | 90.0 | 140.0 | reference | - | `sleep 2` | 3000.0 ± 1000.0 | 2000.0 | 4000.0 | +2627.3% | + | Command | Mean Wall Time [ms] | Change | Factor | + |:---|---:|---:|:---| + | `sleep 0.1` | 110.0 ± 26.5 | | | + | `sleep 2` | 3000.0 ± 1000.0 | +2627.3% | (27.3x slower) | "); insta::assert_snapshot!(get_output::(&results, None), @r#" - [cols="<,>,>,>,>"] + [cols="<,>,>,<"] |=== | Command | Mean Wall Time [ms] - | Min [ms] - | Max [ms] | Change + | Factor | `sleep 0.1` | 110.0 ± 26.5 - | 90.0 - | 140.0 - | reference + | + | | `sleep 2` | 3000.0 ± 1000.0 - | 2000.0 - | 4000.0 | +2627.3% + | (27.3x slower) |=== "#); insta::assert_snapshot!(get_output::(&results, None), @" - | Command | Mean Wall Time [ms] | Min [ms] | Max [ms] | Change | - |--+--+--+--+--| - | =sleep 0.1= | 110.0 ± 26.5 | 90.0 | 140.0 | reference | - | =sleep 2= | 3000.0 ± 1000.0 | 2000.0 | 4000.0 | +2627.3% | + | Command | Mean Wall Time [ms] | Change | Factor | + |--+--+--+--| + | =sleep 0.1= | 110.0 ± 26.5 | | | + | =sleep 2= | 3000.0 ± 1000.0 | +2627.3% | (27.3x slower) | "); } @@ -222,40 +219,37 @@ fn test_markup_export_auto_s() { ]; insta::assert_snapshot!(get_output::(&results, None), @" - | Command | Mean Wall Time [s] | Min [s] | Max [s] | Change | - |:---|---:|---:|---:|---:| - | `sleep 2` | 2.200 ± 0.100 | 2.100 | 2.300 | reference | - | `sleep 0.1` | 0.200 ± 0.100 | 0.100 | 0.300 | -90.9% | + | Command | Mean Wall Time [s] | Change | Factor | + |:---|---:|---:|:---| + | `sleep 2` | 2.200 ± 0.100 | | | + | `sleep 0.1` | 0.200 ± 0.100 | -90.9% | (11.0x faster) | "); insta::assert_snapshot!(get_output::(&results, None), @r#" - [cols="<,>,>,>,>"] + [cols="<,>,>,<"] |=== | Command | Mean Wall Time [s] - | Min [s] - | Max [s] | Change + | Factor | `sleep 2` | 2.200 ± 0.100 - | 2.100 - | 2.300 - | reference + | + | | `sleep 0.1` | 0.200 ± 0.100 - | 0.100 - | 0.300 | -90.9% + | (11.0x faster) |=== "#); insta::assert_snapshot!(get_output::(&results, None), @" - | Command | Mean Wall Time [s] | Min [s] | Max [s] | Change | - |--+--+--+--+--| - | =sleep 2= | 2.200 ± 0.100 | 2.100 | 2.300 | reference | - | =sleep 0.1= | 0.200 ± 0.100 | 0.100 | 0.300 | -90.9% | + | Command | Mean Wall Time [s] | Change | Factor | + |--+--+--+--| + | =sleep 2= | 2.200 ± 0.100 | | | + | =sleep 0.1= | 0.200 ± 0.100 | -90.9% | (11.0x faster) | "); } @@ -337,40 +331,37 @@ fn test_markup_export_manual_ms() { ]; insta::assert_snapshot!(get_output::(&timing_results, Some(Unit { symbol: "ms", scale: 0.001 })), @" - | Command | Mean Wall Time [ms] | Min [ms] | Max [ms] | Change | - |:---|---:|---:|---:|---:| - | `sleep 2` | 2200.0 ± 100.0 | 2100.0 | 2300.0 | reference | - | `sleep 0.1` | 200.0 ± 100.0 | 100.0 | 300.0 | -90.9% | + | Command | Mean Wall Time [ms] | Change | Factor | + |:---|---:|---:|:---| + | `sleep 2` | 2200.0 ± 100.0 | | | + | `sleep 0.1` | 200.0 ± 100.0 | -90.9% | (11.0x faster) | "); insta::assert_snapshot!(get_output::(&timing_results, Some(Unit { symbol: "ms", scale: 0.001 })), @r#" - [cols="<,>,>,>,>"] + [cols="<,>,>,<"] |=== | Command | Mean Wall Time [ms] - | Min [ms] - | Max [ms] | Change + | Factor | `sleep 2` | 2200.0 ± 100.0 - | 2100.0 - | 2300.0 - | reference + | + | | `sleep 0.1` | 200.0 ± 100.0 - | 100.0 - | 300.0 | -90.9% + | (11.0x faster) |=== "#); insta::assert_snapshot!(get_output::(&timing_results, Some(Unit { symbol: "ms", scale: 0.001 })), @" - | Command | Mean Wall Time [ms] | Min [ms] | Max [ms] | Change | - |--+--+--+--+--| - | =sleep 2= | 2200.0 ± 100.0 | 2100.0 | 2300.0 | reference | - | =sleep 0.1= | 200.0 ± 100.0 | 100.0 | 300.0 | -90.9% | + | Command | Mean Wall Time [ms] | Change | Factor | + |--+--+--+--| + | =sleep 2= | 2200.0 ± 100.0 | | | + | =sleep 0.1= | 200.0 ± 100.0 | -90.9% | (11.0x faster) | "); } @@ -451,32 +442,29 @@ fn test_markup_export_manual_s() { ]; insta::assert_snapshot!(get_output::(&results, Some(Unit { symbol: "s", scale: 1.0 })), @" - | Command | Mean Wall Time [s] | Min [s] | Max [s] | Change | - |:---|---:|---:|---:|---:| - | `sleep 2` | 2.020 ± 0.010 | 2.010 | 2.030 | reference | - | `sleep 0.1` | 0.120 ± 0.010 | 0.110 | 0.130 | -94.1% | + | Command | Mean Wall Time [s] | Change | Factor | + |:---|---:|---:|:---| + | `sleep 2` | 2.020 ± 0.010 | | | + | `sleep 0.1` | 0.120 ± 0.010 | -94.1% | (16.8x faster) | "); insta::assert_snapshot!(get_output::(&results, Some(Unit { symbol: "s", scale: 1.0 })), @r#" - [cols="<,>,>,>,>"] + [cols="<,>,>,<"] |=== | Command | Mean Wall Time [s] - | Min [s] - | Max [s] | Change + | Factor | `sleep 2` | 2.020 ± 0.010 - | 2.010 - | 2.030 - | reference + | + | | `sleep 0.1` | 0.120 ± 0.010 - | 0.110 - | 0.130 | -94.1% + | (16.8x faster) |=== "#); } diff --git a/src/metric.rs b/src/metric.rs index 2564650..22a954d 100644 --- a/src/metric.rs +++ b/src/metric.rs @@ -337,16 +337,40 @@ impl Stats { } pub fn format_change_from(&self, reference: &Self) -> String { - match self.change_from(reference) { - Some(change) => { - let formatted = format!("{change:+.1}%"); - if formatted == "+0.0%" || formatted == "-0.0%" { - "0.0%".to_owned() - } else { - formatted - } - } - None => "N/A".to_owned(), + let Some(change) = self.change_from(reference) else { + return "N/A".to_owned(); + }; + let mut formatted = format!("{change:+.1}%"); + if formatted == "+0.0%" || formatted == "-0.0%" { + formatted = "0.0%".to_owned(); + } + formatted + } + + pub fn format_factor_from(&self, reference: &Self, metric: Metric) -> String { + if reference.mean > 0.0 + && (self.mean >= 2.0 * reference.mean || self.mean <= reference.mean / 2.0) + { + let decrease = self.mean < reference.mean; + let factor = if decrease { + reference.mean / self.mean + } else { + self.mean / reference.mean + }; + let direction = match (metric.is_time(), decrease) { + (true, true) => "faster", + (true, false) => "slower", + (false, true) => "less", + (false, false) => "more", + }; + let factor = if factor.is_infinite() { + "∞".to_owned() + } else { + format!("{factor:.1}") + }; + format!("({factor}x {direction})") + } else { + String::new() } } } @@ -356,6 +380,40 @@ mod tests { use super::*; use crate::quantity::{Information, Time}; + #[test] + fn large_changes_include_factors() { + let reference = Stats { + count: 1, + mean: 12.0, + stddev: None, + median: 12.0, + min: 12.0, + max: 12.0, + }; + for (mean, metric, expected) in [ + (24.0, Metric::TimeWallClock, "+100.0% (2.0x slower)"), + (6.0, Metric::TimeCpu, "-50.0% (2.0x faster)"), + (1.2, Metric::Instructions, "-90.0% (10.0x less)"), + (120.0, Metric::MemoryPeakResident, "+900.0% (10.0x more)"), + (23.9, Metric::TimeWallClock, "+99.2%"), + (6.1, Metric::Instructions, "-49.2%"), + (12.0, Metric::Instructions, "0.0%"), + (0.0, Metric::Instructions, "-100.0% (∞x less)"), + ] { + let stats = Stats { mean, ..reference }; + let (percentage, factor) = expected + .split_once(" (") + .map_or((expected, String::new()), |(p, f)| (p, format!("({f}"))); + assert_eq!(stats.format_change_from(&reference), percentage); + assert_eq!(stats.format_factor_from(&reference, metric), factor); + } + let zero = Stats { + mean: 0.0, + ..reference + }; + assert_eq!(reference.format_change_from(&zero), "N/A"); + } + #[test] fn cpu_time_statistics_use_per_run_totals() { let measurements = Measurements::new( diff --git a/src/output/report.rs b/src/output/report.rs index 975cee5..c46b69e 100644 --- a/src/output/report.rs +++ b/src/output/report.rs @@ -11,7 +11,7 @@ use crate::output::console_writeln; // independently printed benchmarks keep the same layout. const MIN_VALUE_WIDTH: usize = 7; const MIN_UNIT_WIDTH: usize = 3; -const MIN_CHANGE_WIDTH: usize = 12; +const MIN_CHANGE_WIDTH: usize = 14; /// Print a completed benchmark immediately, comparing every metric with benchmark 1. pub fn print( @@ -37,7 +37,7 @@ pub fn print( header[1] = "Value".to_owned(); } if comparison { - header.push(String::new()); + header.extend([String::new(), String::new()]); } let mut rows = vec![(header, "")]; for selection in metrics { @@ -71,6 +71,9 @@ pub fn print( || "N/A".to_owned(), |baseline| summary.format_change_from(baseline), )); + row.push(baseline.as_ref().map_or_else(String::new, |baseline| { + summary.format_factor_from(baseline, selection.metric) + })); } rows.push(( row, @@ -131,7 +134,8 @@ pub fn print( for (index, (row, unit)) in rows.iter().enumerate() { let mut line = String::new(); for (column, value) in row.iter().enumerate() { - let is_change = comparison && column == row.len() - 1; + let is_factor = comparison && column == row.len() - 1; + let is_change = comparison && column >= row.len() - 2; if index == 0 && is_change { break; } @@ -150,9 +154,9 @@ pub fn print( value.clone() }; let styled = if is_change { - if value.starts_with('-') { + if row[row.len() - 2].starts_with('-') { text.green().to_string() - } else if value.starts_with('+') { + } else if row[row.len() - 2].starts_with('+') { text.red().to_string() } else { text.normal().to_string() @@ -166,7 +170,7 @@ pub fn print( } else { text.normal().to_string() }; - if column == 0 { + if column == 0 || is_factor { line.push_str(&format!("{styled}{padding}")); } else { line.push_str(&format!("{padding}{styled}")); diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index 47cef60..0f63c4e 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -662,6 +662,28 @@ fn takes_both_preparation_and_conclusion_command_into_account_for_computing_numb .stdout(predicate::str::contains("30 runs")); } +#[test] +fn secondary_metrics_include_factors_for_large_changes() { + // Mock CPU time is zero; secondary wall time still gets ratio annotations. + let output = hyperfine_debug() + .args([ + "--metrics=time_cpu,time_wall_clock", + "--style=basic", + "--runs=2", + "sleep 1", + "sleep 10", + "sleep 0.1", + ]) + .output() + .unwrap(); + assert!(output.status.success(), "{:?}", output); + let stdout = String::from_utf8(output.stdout).unwrap(); + assert!(stdout.contains("+900.0%"), "{}", stdout); + assert!(stdout.contains("-90.0%"), "{}", stdout); + assert!(stdout.contains("+900.0% (10.0x slower)"), "{}", stdout); + assert!(stdout.contains("-90.0% (10.0x faster)"), "{}", stdout); +} + #[test] fn shows_multiple_metrics_relative_to_first_command() { let _settings = snapshot_settings().bind_to_scope(); @@ -682,15 +704,15 @@ fn shows_multiple_metrics_relative_to_first_command() { Benchmark 2: sleep 0.6155 (10 runs) mean ± σ min … max - Wall Time 615.5 ms ± 0.0 ms 615.5 ms … 615.5 ms +653.4% - User time 0.0 µs ± 0.0 µs 0.0 µs … 0.0 µs N/A - Memory 0.0 MiB ± 0.0 MiB 0.0 MiB … 0.0 MiB N/A + Wall Time 615.5 ms ± 0.0 ms 615.5 ms … 615.5 ms +653.4% (7.5x slower) + User time 0.0 µs ± 0.0 µs 0.0 µs … 0.0 µs N/A + Memory 0.0 MiB ± 0.0 MiB 0.0 MiB … 0.0 MiB N/A Benchmark 3: sleep 0.1707 (17 runs) mean ± σ min … max - Wall Time 170.7 ms ± 0.0 ms 170.7 ms … 170.7 ms +108.9% - User time 0.0 µs ± 0.0 µs 0.0 µs … 0.0 µs N/A - Memory 0.0 MiB ± 0.0 MiB 0.0 MiB … 0.0 MiB N/A + Wall Time 170.7 ms ± 0.0 ms 170.7 ms … 170.7 ms +108.9% (2.1x slower) + User time 0.0 µs ± 0.0 µs 0.0 µs … 0.0 µs N/A + Memory 0.0 MiB ± 0.0 MiB 0.0 MiB … 0.0 MiB N/A ----- stderr ----- @@ -719,18 +741,18 @@ fn shows_benchmark_comparison_with_same_time() { Benchmark 2: B (10 runs) mean ± σ min … max - Wall Time 1.000 s ± 0.000 s 1.000 s … 1.000 s 0.0% - Memory 0.0 B ± 0.0 B 0.0 B … 0.0 B N/A + Wall Time 1.000 s ± 0.000 s 1.000 s … 1.000 s 0.0% + Memory 0.0 B ± 0.0 B 0.0 B … 0.0 B N/A Benchmark 3: sleep 2.0 (10 runs) mean ± σ min … max - Wall Time 2.000 s ± 0.000 s 2.000 s … 2.000 s +100.0% - Memory 0.0 B ± 0.0 B 0.0 B … 0.0 B N/A + Wall Time 2.000 s ± 0.000 s 2.000 s … 2.000 s +100.0% (2.0x slower) + Memory 0.0 B ± 0.0 B 0.0 B … 0.0 B N/A Benchmark 4: sleep 1000.0 (10 runs) mean ± σ min … max - Wall Time 1000.000 s ± 0.000 s 1000.000 s … 1000.000 s +99900.0% - Memory 0.0 B ± 0.0 B 0.0 B … 0.0 B N/A + Wall Time 1000.000 s ± 0.000 s 1000.000 s … 1000.000 s +99900.0% (1000.0x slower) + Memory 0.0 B ± 0.0 B 0.0 B … 0.0 B N/A ----- stderr ----- @@ -756,13 +778,13 @@ fn shows_benchmark_comparison_relative_to_reference() { 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% - Memory 0.0 B ± 0.0 B 0.0 B … 0.0 B N/A + 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% - Memory 0.0 B ± 0.0 B 0.0 B … 0.0 B N/A + Wall Time 3.000 s ± 0.000 s 3.000 s … 3.000 s +50.0% + Memory 0.0 B ± 0.0 B 0.0 B … 0.0 B N/A ----- stderr ----- @@ -797,12 +819,12 @@ fn comparison_and_markup_identify_first_command_as_reference() { assert!(stdout.contains("+50.0%"), "{}", stdout); let markdown = std::fs::read_to_string(export_path).unwrap(); insta::assert_snapshot!(markdown, @" - | Command | Mean Wall Time [s] | Min [s] | Max [s] | Change | - |:---|---:|---:|---:|---:| - | `baseline` | 2.000 | 2.000 | 2.000 | reference | - | `sleep 1` | 1.000 | 1.000 | 1.000 | -50.0% | - | `sleep 2` | 2.000 | 2.000 | 2.000 | 0.0% | - | `sleep 3` | 3.000 | 3.000 | 3.000 | +50.0% | + | Command | Mean Wall Time [s] | Change | Factor | + |:---|---:|---:|:---| + | `baseline` | 2.000 | | | + | `sleep 1` | 1.000 | -50.0% | (2.0x faster) | + | `sleep 2` | 2.000 | 0.0% | | + | `sleep 3` | 3.000 | +50.0% | | "); // Equal zero times have no meaningful relative factor. @@ -823,7 +845,7 @@ fn comparison_and_markup_identify_first_command_as_reference() { .lines() .find(|line| line.contains("sleep 0")) .unwrap(); - assert!(row.ends_with("| N/A |"), "{}", row); + assert!(row.ends_with("| N/A | |"), "{}", row); } #[test] @@ -846,13 +868,13 @@ fn shows_name_of_first_command() { 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% - Memory 0.0 B ± 0.0 B 0.0 B … 0.0 B N/A + 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% - Memory 0.0 B ± 0.0 B 0.0 B … 0.0 B N/A + Wall Time 3.000 s ± 0.000 s 3.000 s … 3.000 s +50.0% + Memory 0.0 B ± 0.0 B 0.0 B … 0.0 B N/A ----- stderr ----- @@ -882,18 +904,18 @@ fn performs_all_benchmarks_in_parameter_scan() { Benchmark 2: sleep 35 (10 runs) mean ± σ min … max - Wall Time 35.000 s ± 0.000 s 35.000 s … 35.000 s +16.7% - Memory 0.0 B ± 0.0 B 0.0 B … 0.0 B N/A + Wall Time 35.000 s ± 0.000 s 35.000 s … 35.000 s +16.7% + Memory 0.0 B ± 0.0 B 0.0 B … 0.0 B N/A Benchmark 3: sleep 40 (10 runs) mean ± σ min … max - Wall Time 40.000 s ± 0.000 s 40.000 s … 40.000 s +33.3% - Memory 0.0 B ± 0.0 B 0.0 B … 0.0 B N/A + Wall Time 40.000 s ± 0.000 s 40.000 s … 40.000 s +33.3% + Memory 0.0 B ± 0.0 B 0.0 B … 0.0 B N/A Benchmark 4: sleep 45 (10 runs) mean ± σ min … max - Wall Time 45.000 s ± 0.000 s 45.000 s … 45.000 s +50.0% - Memory 0.0 B ± 0.0 B 0.0 B … 0.0 B N/A + Wall Time 45.000 s ± 0.000 s 45.000 s … 45.000 s +50.0% + Memory 0.0 B ± 0.0 B 0.0 B … 0.0 B N/A ----- stderr ----- @@ -1051,7 +1073,7 @@ fn intermediate_markdown_retains_completed_reference() { .lines() .find(|line| line.contains("sleep 0.01")) .unwrap(); - assert!(row.contains("reference"), "{}", row); + assert!(row.ends_with("| | |"), "{}", row); } #[test] @@ -1074,11 +1096,11 @@ fn markdown_export_uses_first_parameterized_benchmark_as_reference() { exit_code: 0 ----- stdout ----- - | Command | Mean Wall Time [s] | Min [s] | Max [s] | Change | - |:---|---:|---:|---:|---:| - | `case-1` | 1.000 | 1.000 | 1.000 | reference | - | `case-2` | 2.000 | 2.000 | 2.000 | +100.0% | - | `case-3` | 3.000 | 3.000 | 3.000 | +200.0% | + | Command | Mean Wall Time [s] | Change | Factor | + |:---|---:|---:|:---| + | `case-1` | 1.000 | | | + | `case-2` | 2.000 | +100.0% | (2.0x slower) | + | `case-3` | 3.000 | +200.0% | (3.0x slower) | ----- stderr ----- @@ -1098,10 +1120,10 @@ fn intermediate_results_are_not_exported_to_stdout() { exit_code: 0 ----- stdout ----- - | Command | Mean Wall Time [s] | Min [s] | Max [s] | Change | - |:---|---:|---:|---:|---:| - | `sleep 1` | 1.000 ± 0.000 | 1.000 | 1.000 | reference | - | `sleep 2` | 2.000 ± 0.000 | 2.000 | 2.000 | +100.0% | + | Command | Mean Wall Time [s] | Change | Factor | + |:---|---:|---:|:---| + | `sleep 1` | 1.000 ± 0.000 | | | + | `sleep 2` | 2.000 ± 0.000 | +100.0% | (2.0x slower) | ----- stderr ----- @@ -1184,9 +1206,9 @@ fn markdown_export_preserves_backticks_and_pipes_in_command_names() { exit_code: 0 ----- stdout ----- - | Command | Mean Wall Time [s] | Min [s] | Max [s] | Change | - |:---|---:|---:|---:|---:| - | `` echo `uname` \| cat `` | 1.000 ± 0.000 | 1.000 | 1.000 | reference | + | Command | Mean Wall Time [s] | Change | Factor | + |:---|---:|---:|:---| + | `` echo `uname` \| cat `` | 1.000 ± 0.000 | | | ----- stderr -----