Files
hyperfine/src/benchmark/scheduler.rs
T

133 lines
4.9 KiB
Rust
Raw Normal View History

2022-02-20 13:44:34 +01:00
use colored::*;
use super::benchmark_result::BenchmarkResult;
use super::executor::{Executor, MockExecutor, RawExecutor, ShellExecutor};
2022-02-21 08:46:10 +01:00
use super::{relative_speed, Benchmark};
2022-02-20 13:44:34 +01:00
2022-02-07 21:03:23 +01:00
use crate::command::Commands;
use crate::export::ExportManager;
2023-06-03 21:06:50 +02:00
use crate::options::{ExecutorKind, Options, OutputStyleOption, SortOrder};
2022-02-07 21:03:23 +01:00
2022-02-21 08:46:10 +01:00
use anyhow::Result;
2022-02-20 13:44:34 +01:00
2022-02-20 14:04:37 +01:00
pub struct Scheduler<'a> {
commands: &'a Commands<'a>,
options: &'a Options,
export_manager: &'a ExportManager,
results: Vec<BenchmarkResult>,
}
impl<'a> Scheduler<'a> {
pub fn new(
commands: &'a Commands,
options: &'a Options,
export_manager: &'a ExportManager,
) -> Self {
Self {
commands,
options,
export_manager,
results: vec![],
2022-02-20 13:44:34 +01:00
}
}
2022-02-20 14:04:37 +01:00
pub fn run_benchmarks(&mut self) -> Result<()> {
2022-02-22 08:36:56 +01:00
let mut executor: Box<dyn Executor> = match self.options.executor_kind {
ExecutorKind::Raw => Box::new(RawExecutor::new(self.options)),
2022-02-22 08:58:57 +01:00
ExecutorKind::Mock(ref shell) => Box::new(MockExecutor::new(shell.clone())),
2022-02-22 10:13:06 +01:00
ExecutorKind::Shell(ref shell) => Box::new(ShellExecutor::new(shell, self.options)),
2022-02-22 08:36:56 +01:00
};
executor.calibrate()?;
2022-02-20 13:44:34 +01:00
2022-02-21 08:46:10 +01:00
for (number, cmd) in self.commands.iter().enumerate() {
2022-02-20 14:04:37 +01:00
self.results
2022-02-22 08:36:56 +01:00
.push(Benchmark::new(number, cmd, self.options, &*executor).run()?);
2022-02-20 14:04:37 +01:00
// We export results after each individual benchmark, because
// we would risk losing them if a later benchmark fails.
2023-06-03 21:06:50 +02:00
self.export_manager.write_results(
&self.results,
self.options.sort_order_exports,
true,
)?;
2022-02-20 14:04:37 +01:00
}
Ok(())
}
pub fn print_relative_speed_comparison(&self) {
if self.options.output_style == OutputStyleOption::Disabled {
return;
}
if self.results.len() < 2 {
return;
}
2023-06-03 21:06:50 +02:00
if let Some(annotated_results) = relative_speed::compute_with_check(
&self.results,
self.options.sort_order_speed_comparison,
) {
match self.options.sort_order_speed_comparison {
SortOrder::MeanTime => {
println!("{}", "Summary".bold());
2022-02-20 14:04:37 +01:00
2023-06-03 21:06:50 +02:00
let fastest = annotated_results.iter().find(|r| r.is_fastest).unwrap();
let others = annotated_results.iter().filter(|r| !r.is_fastest);
2022-02-20 14:04:37 +01:00
2023-06-03 21:06:50 +02:00
println!(
" {} ran",
fastest.result.command_with_unused_parameters.cyan()
);
2022-02-20 14:04:37 +01:00
2023-06-03 21:06:50 +02:00
for item in others {
println!(
"{}{} times faster than {}",
format!("{:8.2}", item.relative_speed).bold().green(),
if let Some(stddev) = item.relative_speed_stddev {
2024-05-31 13:26:35 -07:00
format!(" ± {}", format!("{stddev:.2}").green())
2023-06-03 21:06:50 +02:00
} else {
"".into()
},
&item.result.command_with_unused_parameters.magenta()
);
}
}
SortOrder::Command => {
println!("{}", "Relative speed comparison".bold());
for item in annotated_results {
println!(
" {}{} {}",
format!("{:10.2}", item.relative_speed).bold().green(),
if item.is_fastest {
" ".into()
2023-06-03 23:24:11 +02:00
} else if let Some(stddev) = item.relative_speed_stddev {
2024-05-31 13:26:35 -07:00
format!(" ± {}", format!("{stddev:5.2}").green())
2023-06-03 21:06:50 +02:00
} else {
2023-06-03 23:24:11 +02:00
" ".into()
2023-06-03 21:06:50 +02:00
},
&item.result.command_with_unused_parameters,
);
}
}
2022-02-20 14:04:37 +01:00
}
2022-02-20 13:44:34 +01:00
} else {
2022-02-20 14:04:37 +01:00
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). \
2023-04-20 12:32:11 +02:00
Try to re-run the benchmark on a quiet system. If you did not do so already, try the \
--shell=none/-N option. If it does not help either, you command is most likely too fast \
to be accurately benchmarked by hyperfine.",
2022-02-20 14:04:37 +01:00
"Note".bold().red()
);
}
}
pub fn final_export(&self) -> Result<()> {
2023-06-03 21:06:50 +02:00
self.export_manager
.write_results(&self.results, self.options.sort_order_exports, false)
}
2022-02-20 13:44:34 +01:00
}