From 579b7627906d206c694528da5cc23ed41f579e5c Mon Sep 17 00:00:00 2001 From: David Peter Date: Mon, 5 Oct 2026 21:02:52 +0200 Subject: [PATCH] Consistent display name --- src/benchmark/benchmark_result.rs | 41 ++++++++++++------------------- src/benchmark/mod.rs | 2 +- src/benchmark/relative_speed.rs | 1 + src/benchmark/scheduler.rs | 10 +++----- src/export/csv.rs | 6 ++--- src/export/markup.rs | 2 +- src/export/tests.rs | 8 ++++++ src/quantity/mod.rs | 4 +-- 8 files changed, 34 insertions(+), 40 deletions(-) diff --git a/src/benchmark/benchmark_result.rs b/src/benchmark/benchmark_result.rs index cbd552d..1d9f597 100644 --- a/src/benchmark/benchmark_result.rs +++ b/src/benchmark/benchmark_result.rs @@ -5,24 +5,35 @@ use serde::Serialize; use crate::benchmark::measurement::Measurements; use crate::quantity::Time; -/// Parameter value and whether it was used in the command line template +/// Parameter value #[derive(Debug, Default, Clone, Serialize, PartialEq)] pub struct Parameter { pub value: String, - #[serde(skip_serializing)] - pub is_unused: bool, } /// Meta data and performance metrics for a single benchmark #[derive(Debug, Default, Clone, Serialize, PartialEq)] pub struct BenchmarkResult { - /// The expanded command line being benchmarked + /// The command line being benchmarked, after parameter substitution. + /// For example, `sleep {duration}` with `duration=1` becomes `sleep 1`, + /// regardless of any custom name. pub command: String, - /// The display name, when it differs from the command line + /// The custom name after parameter substitution, if it differs from `command`. + /// For example, `--command-name="wait {duration}s"` with `duration=1` + /// produces `Some("wait 1s")`. Without a custom name, or when the expanded + /// name equals `command`, this is `None`. #[serde(skip_serializing_if = "Option::is_none")] pub name: Option, + /// The custom name (or `command`), followed by parameters not used in the + /// command template, in command-line order. For example, `sleep {duration}` + /// with `duration=1`, `branch=main`, and the custom name `wait {duration}s` + /// produces `wait 1s (branch = main)`. Without the custom name, this is + /// `sleep 1 (branch = main)`. Used in summaries and table exports. + #[serde(skip_serializing)] + pub display_name: String, + /// Performance metric measurements and exit codes for each run #[serde(flatten)] pub measurements: Measurements, @@ -41,24 +52,4 @@ impl BenchmarkResult { pub fn mean_wall_clock_time(&self) -> Time { self.measurements.time_wall_clock_mean() } - - /// The display name of the command, possibly including a list of - /// parameters that were not used in the command line template. - pub fn command_with_unused_parameters(&self) -> String { - let parameters = self - .parameters - .iter() - .filter(|(_, parameter)| parameter.is_unused) - .fold(String::new(), |output, (name, parameter)| { - output + &format!("{name} = {value}, ", value = parameter.value) - }); - let parameters = parameters.trim_end_matches(", "); - let parameters = if parameters.is_empty() { - "".into() - } else { - format!(" ({parameters})") - }; - - format!("{}{}", self.get_name(), parameters) - } } diff --git a/src/benchmark/mod.rs b/src/benchmark/mod.rs index 3fb8709..39adf92 100644 --- a/src/benchmark/mod.rs +++ b/src/benchmark/mod.rs @@ -482,6 +482,7 @@ impl<'a> Benchmark<'a> { Ok(BenchmarkResult { command, name, + display_name: self.command.get_name_with_unused_parameters(), measurements, parameters: self .command @@ -492,7 +493,6 @@ impl<'a> Benchmark<'a> { name.to_string(), Parameter { value: value.to_string(), - is_unused: self.command.is_parameter_unused(name), }, ) }) diff --git a/src/benchmark/relative_speed.rs b/src/benchmark/relative_speed.rs index b8edc45..3151a01 100644 --- a/src/benchmark/relative_speed.rs +++ b/src/benchmark/relative_speed.rs @@ -158,6 +158,7 @@ fn create_result(name: &str, mean: f64) -> BenchmarkResult { BenchmarkResult { command: name.into(), + display_name: name.into(), name: None, measurements: Measurements { measurements: vec![Measurement { diff --git a/src/benchmark/scheduler.rs b/src/benchmark/scheduler.rs index f618b73..c1297f0 100644 --- a/src/benchmark/scheduler.rs +++ b/src/benchmark/scheduler.rs @@ -89,11 +89,7 @@ impl<'a> Scheduler<'a> { let reference = annotated_results.iter().find(|r| r.is_reference).unwrap(); let others = annotated_results.iter().filter(|r| !r.is_reference); - console_writeln!( - stdout, - " {} ran", - reference.result.command_with_unused_parameters().cyan() - )?; + console_writeln!(stdout, " {} ran", reference.result.display_name.cyan())?; for item in others { let stddev = if let Some(stddev) = item.relative_speed_stddev { @@ -122,7 +118,7 @@ impl<'a> Scheduler<'a> { stdout, "{} {}", comparator, - &item.result.command_with_unused_parameters().magenta() + &item.result.display_name.magenta() )?; } } @@ -146,7 +142,7 @@ impl<'a> Scheduler<'a> { } else { " ".into() }, - item.result.command_with_unused_parameters(), + item.result.display_name, relationship, )?; } diff --git a/src/export/csv.rs b/src/export/csv.rs index e1b9098..5a02fdc 100644 --- a/src/export/csv.rs +++ b/src/export/csv.rs @@ -82,6 +82,7 @@ fn test_csv() { BenchmarkResult { command: String::from("echo command_a"), name: Some(String::from("command_a")), + display_name: String::from("command_a"), measurements: Measurements::new(vec![ Measurement { time_wall_clock: Time::new::(7.0), @@ -111,14 +112,12 @@ fn test_csv() { "foo".into(), Parameter { value: "one".into(), - is_unused: false, }, ); params.insert( "bar".into(), Parameter { value: "two".into(), - is_unused: false, }, ); params @@ -127,6 +126,7 @@ fn test_csv() { BenchmarkResult { command: String::from("command_b"), name: None, + display_name: String::from("command_b"), measurements: Measurements::new(vec![ Measurement { time_wall_clock: Time::new::(17.0), @@ -156,14 +156,12 @@ fn test_csv() { "foo".into(), Parameter { value: "one".into(), - is_unused: false, }, ); params.insert( "bar".into(), Parameter { value: "seven".into(), - is_unused: false, }, ); params diff --git a/src/export/markup.rs b/src/export/markup.rs index 13ac565..a506098 100644 --- a/src/export/markup.rs +++ b/src/export/markup.rs @@ -50,7 +50,7 @@ pub trait MarkupExporter { for entry in entries { let result = &entry.result; // prepare data row strings - let cmd_str = result.command_with_unused_parameters().replace('|', "\\|"); + let cmd_str = result.display_name.replace('|', "\\|"); let mean_str = result.mean_wall_clock_time().format_value(time_unit); let stddev_str = if let Some(stddev) = result.measurements.stddev() { format!(" ± {}", stddev.format_value(time_unit)) diff --git a/src/export/tests.rs b/src/export/tests.rs index 5dc186f..d99d51a 100644 --- a/src/export/tests.rs +++ b/src/export/tests.rs @@ -29,6 +29,7 @@ fn test_markup_export_auto_ms() { BenchmarkResult { command: String::from("sleep 0.1"), name: None, + display_name: String::from("sleep 0.1"), measurements: Measurements::new(vec![ Measurement { time_wall_clock: Time::new::(0.09), @@ -57,6 +58,7 @@ fn test_markup_export_auto_ms() { BenchmarkResult { command: String::from("sleep 2"), name: None, + display_name: String::from("sleep 2"), measurements: Measurements::new(vec![ Measurement { time_wall_clock: Time::new::(2.0), @@ -130,6 +132,7 @@ fn test_markup_export_auto_s() { BenchmarkResult { command: String::from("sleep 2"), name: None, + display_name: String::from("sleep 2"), measurements: Measurements::new(vec![ Measurement { time_wall_clock: Time::new::(2.1), @@ -158,6 +161,7 @@ fn test_markup_export_auto_s() { BenchmarkResult { command: String::from("sleep 0.1"), name: None, + display_name: String::from("sleep 0.1"), measurements: Measurements::new(vec![ Measurement { time_wall_clock: Time::new::(0.1), @@ -231,6 +235,7 @@ fn test_markup_export_manual_ms() { BenchmarkResult { command: String::from("sleep 2"), name: None, + display_name: String::from("sleep 2"), measurements: Measurements::new(vec![ Measurement { time_wall_clock: Time::new::(2.1), @@ -259,6 +264,7 @@ fn test_markup_export_manual_ms() { BenchmarkResult { command: String::from("sleep 0.1"), name: None, + display_name: String::from("sleep 0.1"), measurements: Measurements::new(vec![ Measurement { time_wall_clock: Time::new::(0.1), @@ -331,6 +337,7 @@ fn test_markup_export_manual_s() { BenchmarkResult { command: String::from("sleep 2"), name: None, + display_name: String::from("sleep 2"), measurements: Measurements::new(vec![ Measurement { time_wall_clock: Time::new::(2.01), @@ -359,6 +366,7 @@ fn test_markup_export_manual_s() { BenchmarkResult { command: String::from("sleep 0.1"), name: None, + display_name: String::from("sleep 0.1"), measurements: Measurements::new(vec![ Measurement { time_wall_clock: Time::new::(0.11), diff --git a/src/quantity/mod.rs b/src/quantity/mod.rs index 87cfc7a..98ed20e 100644 --- a/src/quantity/mod.rs +++ b/src/quantity/mod.rs @@ -130,7 +130,7 @@ pub fn serialize_time(t: &Time, s: S) -> Result where S: Serializer, { - let mut state = s.serialize_struct("Time", 3)?; + let mut state = s.serialize_struct("Time", 2)?; state.serialize_field("value", &t.get::())?; state.serialize_field("unit", "second")?; state.end() @@ -140,7 +140,7 @@ pub fn serialize_information(i: &Information, s: S) -> Result())?; state.serialize_field("unit", "byte")?; state.end()