Add --warmup option, closes #1

This commit is contained in:
sharkdp 2018-01-13 20:05:31 +01:00
parent 197f9fbccb
commit 68fdc2c6fc

View File

@ -45,6 +45,20 @@ fn time_shell_command(shell_cmd: &str) -> CmdResult {
CmdResult::new(execution_time_sec, status.success()) CmdResult::new(execution_time_sec, status.success())
} }
/// Return a pre-configured progress bar
fn get_progress_bar(length: u64, msg: &str) -> ProgressBar {
let progressbar_style = ProgressStyle::default_spinner()
.tick_chars("⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏")
.template(" {spinner} {msg:<28} {wide_bar} ETA {eta_precise}");
let bar = ProgressBar::new(length);
bar.set_style(progressbar_style.clone());
bar.enable_steady_tick(80);
bar.set_message(msg);
bar
}
fn main() { fn main() {
let matches = App::new("hyperfine") let matches = App::new("hyperfine")
.global_settings(&[AppSettings::ColoredHelp]) .global_settings(&[AppSettings::ColoredHelp])
@ -57,15 +71,19 @@ fn main() {
.required(true) .required(true)
.multiple(true), .multiple(true),
) )
.arg(
Arg::with_name("warmup")
.long("warmup")
.short("w")
.takes_value(true)
.value_name("NUM")
.help("Perform NUM warmup runs before the actual benchmark"),
)
.get_matches(); .get_matches();
let min_time_sec = 5.0; let min_time_sec = 5.0;
let min_runs = 10; let min_runs = 10;
let progressbar_style = ProgressStyle::default_spinner()
.tick_chars("⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏")
.template(" {spinner} {msg:<30} {wide_bar} ETA {eta_precise}");
let commands = matches.values_of("command").unwrap(); let commands = matches.values_of("command").unwrap();
for cmd in commands { for cmd in commands {
@ -74,13 +92,24 @@ fn main() {
let mut results = vec![]; let mut results = vec![];
// Set up progress bar // Warmup phase
let bar = ProgressBar::new(min_runs); if let Some(warmup_count) = matches
bar.set_style(progressbar_style.clone()); .value_of("warmup")
bar.enable_steady_tick(80); .and_then(|n| u64::from_str_radix(n, 10).ok())
bar.set_message("Initial time measurement"); {
let bar = get_progress_bar(warmup_count, "Performing warmup runs");
// Initial run for _ in 1..warmup_count {
bar.inc(1);
let _ = time_shell_command(cmd);
}
bar.finish_and_clear();
}
// Set up progress bar (and spinner for initial measurement)
let bar = get_progress_bar(min_runs, "Initial time measurement");
// Initial timing run
let res = time_shell_command(cmd); let res = time_shell_command(cmd);
let runs_in_min_time = (min_time_sec / res.execution_time_sec) as u64; let runs_in_min_time = (min_time_sec / res.execution_time_sec) as u64;
@ -91,11 +120,14 @@ fn main() {
min_runs min_runs
}; };
// Save the first result
results.push(res); results.push(res);
// Re-configure the progress bar
bar.set_length(count); bar.set_length(count);
bar.set_message("Collecting statistics"); bar.set_message("Collecting statistics");
// Gather statistics
for _ in 1..count { for _ in 1..count {
bar.inc(1); bar.inc(1);
let res = time_shell_command(cmd); let res = time_shell_command(cmd);
@ -103,6 +135,7 @@ fn main() {
} }
bar.finish_and_clear(); bar.finish_and_clear();
// Compute statistical quantities
let t_sum: f64 = results.iter().map(|r| r.execution_time_sec).sum(); let t_sum: f64 = results.iter().map(|r| r.execution_time_sec).sum();
let t_mean = t_sum / (results.len() as f64); let t_mean = t_sum / (results.len() as f64);
@ -111,6 +144,7 @@ fn main() {
let stddev = (t2_mean - t_mean.powi(2)).sqrt(); let stddev = (t2_mean - t_mean.powi(2)).sqrt();
// Formatting and console output
let time_fmt = format!("{:.3} s ± {:.3} s", t_mean, stddev); let time_fmt = format!("{:.3} s ± {:.3} s", t_mean, stddev);
println!(" Time: {}", Green.paint(time_fmt)); println!(" Time: {}", Green.paint(time_fmt));