From c5a2266199b7556799fce8bfca05a8822ba13e61 Mon Sep 17 00:00:00 2001 From: David Peter Date: Sun, 6 Feb 2022 20:10:40 +0100 Subject: [PATCH] New schedule module --- src/benchmark/mod.rs | 1 + src/benchmark/schedule.rs | 80 ++++++++++++++++++++++++++++++++++++++ src/main.rs | 82 ++------------------------------------- 3 files changed, 85 insertions(+), 78 deletions(-) create mode 100644 src/benchmark/schedule.rs diff --git a/src/benchmark/mod.rs b/src/benchmark/mod.rs index 5294368..a32605e 100644 --- a/src/benchmark/mod.rs +++ b/src/benchmark/mod.rs @@ -1,5 +1,6 @@ pub mod relative_speed; pub mod result; +pub mod schedule; use std::cmp; use std::process::{ExitStatus, Stdio}; diff --git a/src/benchmark/schedule.rs b/src/benchmark/schedule.rs new file mode 100644 index 0000000..5251bbd --- /dev/null +++ b/src/benchmark/schedule.rs @@ -0,0 +1,80 @@ +use crate::options::{Options, OutputStyleOption}; +use crate::{command::Command, export::ExportManager}; + +use super::{mean_shell_spawning_time, relative_speed, result::BenchmarkResult, run_benchmark}; + +use anyhow::{bail, Result}; +use colored::*; + +pub fn write_benchmark_comparison(results: &[BenchmarkResult]) { + if results.len() < 2 { + return; + } + + if let Some(mut annotated_results) = relative_speed::compute(results) { + annotated_results.sort_by(|l, r| relative_speed::compare_mean_time(l.result, r.result)); + + let fastest = &annotated_results[0]; + let others = &annotated_results[1..]; + + println!("{}", "Summary".bold()); + println!(" '{}' ran", fastest.result.command.cyan()); + + for item in others { + println!( + "{}{} 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() + ); + } + } else { + eprintln!( + "{}: The benchmark comparison could not be computed as some benchmark times are zero. \ + This could be caused by background interference during the initial calibration phase \ + of hyperfine, in combination with very fast commands (faster than a few milliseconds). \ + Try to re-run the benchmark on a quiet system. If it does not help, you command is \ + most likely too fast to be accurately benchmarked by hyperfine.", + "Note".bold().red() + ); + } +} + +pub fn run_benchmarks_and_print_comparison( + commands: &[Command<'_>], + options: &Options, + export_manager: &ExportManager, +) -> Result<()> { + let shell_spawning_time = + mean_shell_spawning_time(&options.shell, options.output_style, options.show_output)?; + + let mut timing_results = vec![]; + + if let Some(preparation_command) = &options.preparation_command { + if preparation_command.len() > 1 && commands.len() != preparation_command.len() { + bail!( + "The '--prepare' option has to be provided just once or N times, where N is the \ + number of benchmark commands." + ); + } + } + + // Run the benchmarks + for (num, cmd) in commands.iter().enumerate() { + timing_results.push(run_benchmark(num, cmd, shell_spawning_time, options)?); + + // Export (intermediate) results + export_manager.write_results(&timing_results, options.time_unit)?; + } + + // Print relative speed comparison + if options.output_style != OutputStyleOption::Disabled { + write_benchmark_comparison(&timing_results); + } + + Ok(()) +} diff --git a/src/main.rs b/src/main.rs index b90b3ba..6826cff 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,12 @@ use std::env; use app::get_arg_matches; -use benchmark::result::BenchmarkResult; -use benchmark::{mean_shell_spawning_time, relative_speed, run_benchmark}; -use command::{build_commands, Command}; +use benchmark::schedule::run_benchmarks_and_print_comparison; +use command::build_commands; use export::ExportManager; -use options::{Options, OutputStyleOption}; +use options::Options; -use anyhow::{bail, Result}; +use anyhow::Result; use colored::*; pub mod app; @@ -23,79 +22,6 @@ pub mod shell; pub mod timer; pub mod util; -pub fn write_benchmark_comparison(results: &[BenchmarkResult]) { - if results.len() < 2 { - return; - } - - if let Some(mut annotated_results) = relative_speed::compute(results) { - annotated_results.sort_by(|l, r| relative_speed::compare_mean_time(l.result, r.result)); - - let fastest = &annotated_results[0]; - let others = &annotated_results[1..]; - - println!("{}", "Summary".bold()); - println!(" '{}' ran", fastest.result.command.cyan()); - - for item in others { - println!( - "{}{} 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() - ); - } - } else { - eprintln!( - "{}: The benchmark comparison could not be computed as some benchmark times are zero. \ - This could be caused by background interference during the initial calibration phase \ - of hyperfine, in combination with very fast commands (faster than a few milliseconds). \ - Try to re-run the benchmark on a quiet system. If it does not help, you command is \ - most likely too fast to be accurately benchmarked by hyperfine.", - "Note".bold().red() - ); - } -} - -fn run_benchmarks_and_print_comparison( - commands: &[Command<'_>], - options: &Options, - export_manager: &ExportManager, -) -> Result<()> { - let shell_spawning_time = - mean_shell_spawning_time(&options.shell, options.output_style, options.show_output)?; - - let mut timing_results = vec![]; - - if let Some(preparation_command) = &options.preparation_command { - if preparation_command.len() > 1 && commands.len() != preparation_command.len() { - bail!( - "The '--prepare' option has to be provided just once or N times, where N is the \ - number of benchmark commands." - ); - } - } - - // Run the benchmarks - for (num, cmd) in commands.iter().enumerate() { - timing_results.push(run_benchmark(num, cmd, shell_spawning_time, options)?); - - // Export (intermediate) results - export_manager.write_results(&timing_results, options.time_unit)?; - } - - // Print relative speed comparison - if options.output_style != OutputStyleOption::Disabled { - write_benchmark_comparison(&timing_results); - } - - Ok(()) -} - fn run() -> Result<()> { // Enabled ANSI colors on Windows 10 #[cfg(windows)]