Show unused parameters in command names

closes #600
This commit is contained in:
David Peter 2023-04-20 21:32:06 +02:00 committed by David Peter
parent 4b9cd06d86
commit a8752769ab
11 changed files with 85 additions and 10 deletions

View File

@ -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,

View File

@ -112,13 +112,12 @@ impl<'a> Benchmark<'a> {
/// Run the benchmark for a single command
pub fn run(&self) -> Result<BenchmarkResult> {
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,

View File

@ -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,

View File

@ -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 {

View File

@ -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::<String>();
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<Item = &(&'a str, ParameterValue)> {
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::<String, String>::new();

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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)")),
);
}