mirror of
https://github.com/sharkdp/hyperfine.git
synced 2024-09-11 14:07:02 +03:00
New Scheduler struct
This commit is contained in:
parent
39984a3896
commit
72d27729fa
@ -1,6 +1,6 @@
|
||||
pub mod relative_speed;
|
||||
pub mod result;
|
||||
pub mod schedule;
|
||||
pub mod scheduler;
|
||||
|
||||
use std::cmp;
|
||||
use std::process::{ExitStatus, Stdio};
|
||||
|
@ -1,81 +0,0 @@
|
||||
use crate::command::Commands;
|
||||
use crate::export::ExportManager;
|
||||
use crate::options::{Options, OutputStyleOption};
|
||||
|
||||
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: &Commands,
|
||||
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(())
|
||||
}
|
92
src/benchmark/scheduler.rs
Normal file
92
src/benchmark/scheduler.rs
Normal file
@ -0,0 +1,92 @@
|
||||
use crate::command::Commands;
|
||||
use crate::export::ExportManager;
|
||||
use crate::options::{Options, OutputStyleOption};
|
||||
|
||||
use super::{mean_shell_spawning_time, relative_speed, result::BenchmarkResult, run_benchmark};
|
||||
|
||||
use anyhow::Result;
|
||||
use colored::*;
|
||||
|
||||
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![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_benchmarks(&mut self) -> Result<()> {
|
||||
let shell_spawning_time = mean_shell_spawning_time(
|
||||
&self.options.shell,
|
||||
self.options.output_style,
|
||||
self.options.show_output,
|
||||
)?;
|
||||
|
||||
// Run the benchmarks
|
||||
for (num, cmd) in self.commands.iter().enumerate() {
|
||||
self.results
|
||||
.push(run_benchmark(num, cmd, shell_spawning_time, self.options)?);
|
||||
|
||||
// Export (intermediate) results
|
||||
self.export_manager
|
||||
.write_results(&self.results, self.options.time_unit)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn print_relative_speed_comparison(&self) {
|
||||
if self.options.output_style == OutputStyleOption::Disabled {
|
||||
return;
|
||||
}
|
||||
|
||||
if self.results.len() < 2 {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(mut annotated_results) = relative_speed::compute(&self.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()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
10
src/main.rs
10
src/main.rs
@ -1,7 +1,7 @@
|
||||
use std::env;
|
||||
|
||||
use app::get_cli_arguments;
|
||||
use benchmark::schedule::run_benchmarks_and_print_comparison;
|
||||
use benchmark::scheduler::Scheduler;
|
||||
use command::Commands;
|
||||
use export::ExportManager;
|
||||
use options::Options;
|
||||
@ -32,7 +32,13 @@ fn run() -> Result<()> {
|
||||
let commands = Commands::from_cli_arguments(&cli_arguments)?;
|
||||
let export_manager = ExportManager::from_cli_arguments(&cli_arguments)?;
|
||||
|
||||
run_benchmarks_and_print_comparison(&commands, &options, &export_manager)
|
||||
options.validate_against_command_list(&commands)?;
|
||||
|
||||
let mut scheduler = Scheduler::new(&commands, &options, &export_manager);
|
||||
scheduler.run_benchmarks()?;
|
||||
scheduler.print_relative_speed_comparison();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -1,12 +1,16 @@
|
||||
use std::process::Command;
|
||||
use std::{cmp, fmt};
|
||||
|
||||
use anyhow::ensure;
|
||||
use atty::Stream;
|
||||
use clap::ArgMatches;
|
||||
|
||||
use crate::command::Commands;
|
||||
use crate::error::OptionsError;
|
||||
use crate::util::units::{Second, Unit};
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
#[cfg(not(windows))]
|
||||
pub const DEFAULT_SHELL: &str = "sh";
|
||||
|
||||
@ -256,6 +260,18 @@ impl Options {
|
||||
|
||||
Ok(options)
|
||||
}
|
||||
|
||||
pub fn validate_against_command_list(&self, commands: &Commands) -> Result<()> {
|
||||
if let Some(preparation_command) = &self.preparation_command {
|
||||
ensure!(
|
||||
preparation_command.len() <= 1 || commands.len() == preparation_command.len(),
|
||||
"The '--prepare' option has to be provided just once or N times, where N is the \
|
||||
number of benchmark commands."
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -44,6 +44,7 @@ fn fails_with_wrong_number_of_prepare_options() {
|
||||
.success();
|
||||
|
||||
hyperfine()
|
||||
.arg("--runs=1")
|
||||
.arg("--prepare=echo a")
|
||||
.arg("--prepare=echo b")
|
||||
.arg("echo a")
|
||||
|
Loading…
Reference in New Issue
Block a user