diff --git a/src/benchmark/benchmark_result.rs b/src/benchmark/benchmark_result.rs index 26714c7..b37f725 100644 --- a/src/benchmark/benchmark_result.rs +++ b/src/benchmark/benchmark_result.rs @@ -12,6 +12,11 @@ pub struct BenchmarkResult { /// The full command line of the program that is being benchmarked pub command: String, + /// The full command line of the program that is being benchmarked, possibly including a list of + /// parameters that were not used in the command line template. + #[serde(skip_serializing)] + pub command_with_unused_parameters: String, + /// The average run time pub mean: Second, diff --git a/src/benchmark/mod.rs b/src/benchmark/mod.rs index 00402a3..6728cc1 100644 --- a/src/benchmark/mod.rs +++ b/src/benchmark/mod.rs @@ -112,13 +112,12 @@ impl<'a> Benchmark<'a> { /// Run the benchmark for a single command pub fn run(&self) -> Result { - let command_name = self.command.get_name(); if self.options.output_style != OutputStyleOption::Disabled { println!( "{}{}: {}", "Benchmark ".bold(), (self.number + 1).to_string().bold(), - command_name, + self.command.get_name_with_unused_parameters(), ); } @@ -369,7 +368,8 @@ impl<'a> Benchmark<'a> { self.run_cleanup_command(self.command.get_parameters().iter().cloned())?; Ok(BenchmarkResult { - command: command_name, + command: self.command.get_name(), + command_with_unused_parameters: self.command.get_name_with_unused_parameters(), mean: t_mean, stddev: t_stddev, median: t_median, diff --git a/src/benchmark/relative_speed.rs b/src/benchmark/relative_speed.rs index ad9ad5a..d7a842d 100644 --- a/src/benchmark/relative_speed.rs +++ b/src/benchmark/relative_speed.rs @@ -89,6 +89,7 @@ fn create_result(name: &str, mean: Scalar) -> BenchmarkResult { BenchmarkResult { command: name.into(), + command_with_unused_parameters: name.into(), mean, stddev: Some(1.0), median: mean, diff --git a/src/benchmark/scheduler.rs b/src/benchmark/scheduler.rs index 1c86f4a..ced4833 100644 --- a/src/benchmark/scheduler.rs +++ b/src/benchmark/scheduler.rs @@ -68,18 +68,21 @@ impl<'a> Scheduler<'a> { let others = &annotated_results[1..]; println!("{}", "Summary".bold()); - println!(" '{}' ran", fastest.result.command.cyan()); + println!( + " {} ran", + fastest.result.command_with_unused_parameters.cyan() + ); for item in others { println!( - "{}{} times faster than '{}'", + "{}{} times faster than {}", format!("{:8.2}", item.relative_speed).bold().green(), if let Some(stddev) = item.relative_speed_stddev { format!(" ± {}", format!("{:.2}", stddev).green()) } else { "".into() }, - &item.result.command.magenta() + &item.result.command_with_unused_parameters.magenta() ); } } else { diff --git a/src/command.rs b/src/command.rs index 2ce651f..4a98406 100644 --- a/src/command.rs +++ b/src/command.rs @@ -2,6 +2,8 @@ use std::collections::BTreeMap; use std::fmt; use std::str::FromStr; +use crate::parameter::tokenize::tokenize; +use crate::parameter::ParameterValue; use crate::{ error::{OptionsError, ParameterScanError}, parameter::{ @@ -12,9 +14,6 @@ use crate::{ use clap::{parser::ValuesRef, ArgMatches}; -use crate::parameter::tokenize::tokenize; -use crate::parameter::ParameterValue; - use anyhow::{bail, Context, Result}; use rust_decimal::Decimal; @@ -59,6 +58,23 @@ impl<'a> Command<'a> { ) } + pub fn get_name_with_unused_parameters(&self) -> String { + let parameters = self + .get_unused_parameters() + .map(|(parameter, value)| { + format!("{} = {}, ", parameter.to_string(), value.to_string()) + }) + .collect::(); + let parameters = parameters.trim_end_matches(", "); + let parameters = if parameters.is_empty() { + "".into() + } else { + format!(" ({})", parameters) + }; + + format!("{}{}", self.get_name(), parameters) + } + pub fn get_command_line(&self) -> String { self.replace_parameters_in(self.expression) } @@ -82,6 +98,12 @@ impl<'a> Command<'a> { &self.parameters } + pub fn get_unused_parameters(&self) -> impl Iterator { + self.parameters + .iter() + .filter(move |(parameter, _)| !self.expression.contains(&format!("{{{}}}", parameter))) + } + fn replace_parameters_in(&self, original: &str) -> String { let mut result = String::new(); let mut replacements = BTreeMap::::new(); diff --git a/src/export/asciidoc.rs b/src/export/asciidoc.rs index 3b5be53..9133d6c 100644 --- a/src/export/asciidoc.rs +++ b/src/export/asciidoc.rs @@ -94,6 +94,7 @@ fn test_asciidoc_format_s() { let results = vec![ BenchmarkResult { command: String::from("FOO=1 BAR=2 command | 1"), + command_with_unused_parameters: String::from("FOO=1 BAR=2 command | 1"), mean: 1.0, stddev: Some(2.0), median: 1.0, @@ -112,6 +113,7 @@ fn test_asciidoc_format_s() { }, BenchmarkResult { command: String::from("FOO=1 BAR=7 command | 2"), + command_with_unused_parameters: String::from("FOO=1 BAR=7 command | 2"), mean: 11.0, stddev: Some(12.0), median: 11.0, @@ -163,6 +165,7 @@ fn test_asciidoc_format_ms() { let results = vec![ BenchmarkResult { command: String::from("FOO=1 BAR=7 command | 2"), + command_with_unused_parameters: String::from("FOO=1 BAR=7 command | 2"), mean: 0.011, stddev: Some(0.012), median: 0.011, @@ -181,6 +184,7 @@ fn test_asciidoc_format_ms() { }, BenchmarkResult { command: String::from("FOO=1 BAR=2 command | 1"), + command_with_unused_parameters: String::from("FOO=1 BAR=2 command | 1"), mean: 1.0, stddev: Some(2.0), median: 1.0, diff --git a/src/export/csv.rs b/src/export/csv.rs index f550f5f..c846a95 100644 --- a/src/export/csv.rs +++ b/src/export/csv.rs @@ -62,6 +62,7 @@ fn test_csv() { let results = vec![ BenchmarkResult { command: String::from("FOO=one BAR=two command | 1"), + command_with_unused_parameters: String::from("FOO=one BAR=two command | 1"), mean: 1.0, stddev: Some(2.0), median: 1.0, @@ -80,6 +81,7 @@ fn test_csv() { }, BenchmarkResult { command: String::from("FOO=one BAR=seven command | 2"), + command_with_unused_parameters: String::from("FOO=one BAR=seven command | 2"), mean: 11.0, stddev: Some(12.0), median: 11.0, diff --git a/src/export/markdown.rs b/src/export/markdown.rs index 44651c3..ba6623b 100644 --- a/src/export/markdown.rs +++ b/src/export/markdown.rs @@ -71,6 +71,7 @@ fn test_markdown_format_ms() { let timing_results = vec![ BenchmarkResult { command: String::from("sleep 0.1"), + command_with_unused_parameters: String::from("sleep 0.1"), mean: 0.1057, stddev: Some(0.0016), median: 0.1057, @@ -84,6 +85,7 @@ fn test_markdown_format_ms() { }, BenchmarkResult { command: String::from("sleep 2"), + command_with_unused_parameters: String::from("sleep 2"), mean: 2.0050, stddev: Some(0.0020), median: 2.0050, @@ -121,6 +123,7 @@ fn test_markdown_format_s() { let timing_results = vec![ BenchmarkResult { command: String::from("sleep 2"), + command_with_unused_parameters: String::from("sleep 2"), mean: 2.0050, stddev: Some(0.0020), median: 2.0050, @@ -134,6 +137,7 @@ fn test_markdown_format_s() { }, BenchmarkResult { command: String::from("sleep 0.1"), + command_with_unused_parameters: String::from("sleep 0.1"), mean: 0.1057, stddev: Some(0.0016), median: 0.1057, @@ -171,6 +175,7 @@ fn test_markdown_format_time_unit_s() { let timing_results = vec![ BenchmarkResult { command: String::from("sleep 0.1"), + command_with_unused_parameters: String::from("sleep 0.1"), mean: 0.1057, stddev: Some(0.0016), median: 0.1057, @@ -184,6 +189,7 @@ fn test_markdown_format_time_unit_s() { }, BenchmarkResult { command: String::from("sleep 2"), + command_with_unused_parameters: String::from("sleep 2"), mean: 2.0050, stddev: Some(0.0020), median: 2.0050, @@ -227,6 +233,7 @@ fn test_markdown_format_time_unit_ms() { let timing_results = vec![ BenchmarkResult { command: String::from("sleep 2"), + command_with_unused_parameters: String::from("sleep 2"), mean: 2.0050, stddev: Some(0.0020), median: 2.0050, @@ -240,6 +247,7 @@ fn test_markdown_format_time_unit_ms() { }, BenchmarkResult { command: String::from("sleep 0.1"), + command_with_unused_parameters: String::from("sleep 0.1"), mean: 0.1057, stddev: Some(0.0016), median: 0.1057, diff --git a/src/export/markup.rs b/src/export/markup.rs index 6984225..c789f3a 100644 --- a/src/export/markup.rs +++ b/src/export/markup.rs @@ -43,7 +43,9 @@ pub trait MarkupExporter { for entry in entries { let measurement = &entry.result; // prepare data row strings - let cmd_str = measurement.command.replace('|', "\\|"); + let cmd_str = measurement + .command_with_unused_parameters + .replace('|', "\\|"); let mean_str = format_duration_value(measurement.mean, Some(unit)).0; let stddev_str = if let Some(stddev) = measurement.stddev { format!(" ± {}", format_duration_value(stddev, Some(unit)).0) @@ -119,6 +121,7 @@ fn test_determine_unit_from_results_unit_given_s() { let results = vec![ BenchmarkResult { command: String::from("sleep 2"), + command_with_unused_parameters: String::from("sleep 2"), mean: 2.0050, stddev: Some(0.0020), median: 2.0050, @@ -132,6 +135,7 @@ fn test_determine_unit_from_results_unit_given_s() { }, BenchmarkResult { command: String::from("sleep 0.1"), + command_with_unused_parameters: String::from("sleep 0.1"), mean: 0.1057, stddev: Some(0.0016), median: 0.1057, @@ -159,6 +163,7 @@ fn test_determine_unit_from_results_unit_given_ms() { let results = vec![ BenchmarkResult { command: String::from("sleep 2"), + command_with_unused_parameters: String::from("sleep 2"), mean: 2.0050, stddev: Some(0.0020), median: 2.0050, @@ -172,6 +177,7 @@ fn test_determine_unit_from_results_unit_given_ms() { }, BenchmarkResult { command: String::from("sleep 0.1"), + command_with_unused_parameters: String::from("sleep 0.1"), mean: 0.1057, stddev: Some(0.0016), median: 0.1057, @@ -199,6 +205,7 @@ fn test_determine_unit_from_results_unit_first_s() { let results = vec![ BenchmarkResult { command: String::from("sleep 2"), + command_with_unused_parameters: String::from("sleep 2"), mean: 2.0050, stddev: Some(0.0020), median: 2.0050, @@ -212,6 +219,7 @@ fn test_determine_unit_from_results_unit_first_s() { }, BenchmarkResult { command: String::from("sleep 0.1"), + command_with_unused_parameters: String::from("sleep 0.1"), mean: 0.1057, stddev: Some(0.0016), median: 0.1057, @@ -239,6 +247,7 @@ fn test_determine_unit_from_results_unit_first_ms() { let results = vec![ BenchmarkResult { command: String::from("sleep 0.1"), + command_with_unused_parameters: String::from("sleep 0.1"), mean: 0.1057, stddev: Some(0.0016), median: 0.1057, @@ -252,6 +261,7 @@ fn test_determine_unit_from_results_unit_first_ms() { }, BenchmarkResult { command: String::from("sleep 2"), + command_with_unused_parameters: String::from("sleep 2"), mean: 2.0050, stddev: Some(0.0020), median: 2.0050, diff --git a/src/export/orgmode.rs b/src/export/orgmode.rs index 42c15e5..8ec8792 100644 --- a/src/export/orgmode.rs +++ b/src/export/orgmode.rs @@ -77,6 +77,7 @@ fn test_orgmode_format_ms() { let results = vec![ BenchmarkResult { command: String::from("sleep 0.1"), + command_with_unused_parameters: String::from("sleep 0.1"), mean: 0.1057, stddev: Some(0.0016), median: 0.1057, @@ -90,6 +91,7 @@ fn test_orgmode_format_ms() { }, BenchmarkResult { command: String::from("sleep 2"), + command_with_unused_parameters: String::from("sleep 2"), mean: 2.0050, stddev: Some(0.0020), median: 2.0050, @@ -129,6 +131,7 @@ fn test_orgmode_format_s() { let results = vec![ BenchmarkResult { command: String::from("sleep 2"), + command_with_unused_parameters: String::from("sleep 2"), mean: 2.0050, stddev: Some(0.0020), median: 2.0050, @@ -142,6 +145,7 @@ fn test_orgmode_format_s() { }, BenchmarkResult { command: String::from("sleep 0.1"), + command_with_unused_parameters: String::from("sleep 0.1"), mean: 0.1057, stddev: Some(0.0016), median: 0.1057, diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index 7930d8d..ed5cdc5 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -382,3 +382,19 @@ fn exports_intermediate_results_to_file() { let contents = std::fs::read_to_string(export_path).unwrap(); assert!(contents.contains("true")); } + +#[test] +fn unused_parameters_are_shown_in_benchmark_name() { + hyperfine() + .arg("--runs=2") + .arg("--parameter-list") + .arg("branch") + .arg("master,feature") + .arg("echo test") + .assert() + .success() + .stdout( + predicate::str::contains("echo test (branch = master)") + .and(predicate::str::contains("echo test (branch = feature)")), + ); +}