-
-
Notifications
You must be signed in to change notification settings - Fork 376
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement slowness checking and --reference flag to use a command as a reference when printing or exporting summary #579
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -4,7 +4,7 @@ use super::benchmark_result::BenchmarkResult; | |||||
use super::executor::{Executor, MockExecutor, RawExecutor, ShellExecutor}; | ||||||
use super::{relative_speed, Benchmark}; | ||||||
|
||||||
use crate::command::Commands; | ||||||
use crate::command::{Command, Commands}; | ||||||
use crate::export::ExportManager; | ||||||
use crate::options::{ExecutorKind, Options, OutputStyleOption}; | ||||||
|
||||||
|
@@ -40,7 +40,12 @@ impl<'a> Scheduler<'a> { | |||||
|
||||||
executor.calibrate()?; | ||||||
|
||||||
for (number, cmd) in self.commands.iter().enumerate() { | ||||||
let reference = self | ||||||
.options | ||||||
.reference_command | ||||||
.as_ref() | ||||||
.map(|cmd| Command::new(None, &cmd)); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
for (number, cmd) in reference.iter().chain(self.commands.iter()).enumerate() { | ||||||
self.results | ||||||
.push(Benchmark::new(number, cmd, self.options, &*executor).run()?); | ||||||
|
||||||
|
@@ -62,24 +67,36 @@ impl<'a> Scheduler<'a> { | |||||
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 reference = self | ||||||
.options | ||||||
.reference_command | ||||||
.as_ref() | ||||||
.map(|_| &self.results[0]) | ||||||
.unwrap_or_else(|| relative_speed::fastest(&self.results)); | ||||||
|
||||||
if let Some(mut annotated_results) = relative_speed::compute(reference, &self.results) { | ||||||
if self.options.reference_command.is_none() { | ||||||
annotated_results | ||||||
.sort_by(|l, r| relative_speed::compare_mean_time(l.result, r.result)); | ||||||
} | ||||||
|
||||||
let fastest = &annotated_results[0]; | ||||||
let reference = &annotated_results[0]; | ||||||
let others = &annotated_results[1..]; | ||||||
|
||||||
println!("{}", "Summary".bold()); | ||||||
println!(" '{}' ran", fastest.result.command.cyan()); | ||||||
println!(" '{}' ran", reference.result.command.cyan()); | ||||||
|
||||||
for item in others { | ||||||
let comparator = if item.is_faster { "faster" } else { "slower" }; | ||||||
println!( | ||||||
"{}{} times faster than '{}'", | ||||||
"{}{} times {} than '{}'", | ||||||
format!("{:8.2}", item.relative_speed).bold().green(), | ||||||
if let Some(stddev) = item.relative_speed_stddev { | ||||||
format!(" ± {}", format!("{:.2}", stddev).green()) | ||||||
} else { | ||||||
"".into() | ||||||
}, | ||||||
comparator, | ||||||
&item.result.command.magenta() | ||||||
); | ||||||
} | ||||||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -68,6 +68,15 @@ fn build_command() -> Command<'static> { | |||||
.help("Perform exactly NUM runs for each command. If this option is not specified, \ | ||||||
hyperfine automatically determines the number of runs."), | ||||||
) | ||||||
.arg( | ||||||
Arg::new("reference") | ||||||
.long("reference") | ||||||
.short('R') | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's not introduce a short command line option for this right away. We can always add it later if this is really a commonly used option. |
||||||
.takes_value(true) | ||||||
.number_of_values(1) | ||||||
.value_name("CMD") | ||||||
.help("The reference command to measure the results against."), | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
) | ||||||
.arg( | ||||||
Arg::new("setup") | ||||||
.long("setup") | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -178,6 +178,9 @@ pub struct Options { | |
/// Whether or not to ignore non-zero exit codes | ||
pub command_failure_action: CmdFailureAction, | ||
|
||
/// Command to run before each *batch* of timing runs, i.e. before each individual benchmark | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Copy & paste error? |
||
pub reference_command: Option<String>, | ||
|
||
/// Command(s) to run before each timing run | ||
pub preparation_command: Option<Vec<String>>, | ||
|
||
|
@@ -207,6 +210,7 @@ impl Default for Options { | |
warmup_count: 0, | ||
min_benchmarking_time: 3.0, | ||
command_failure_action: CmdFailureAction::RaiseError, | ||
reference_command: None, | ||
preparation_command: None, | ||
setup_command: None, | ||
cleanup_command: None, | ||
|
@@ -260,6 +264,8 @@ impl Options { | |
(None, None) => {} | ||
}; | ||
|
||
options.reference_command = matches.value_of("reference").map(String::from); | ||
|
||
options.setup_command = matches.value_of("setup").map(String::from); | ||
|
||
options.preparation_command = matches | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe rename the latter to
Thinking about this some more, it's actually not clear what the value of the latter bool should be for the case where
is_reference
istrue
. So maybe introduce an enum insteadpub enum RelativeOrdering { Reference, FasterThanReference, SlowerThanReference }
and use this instead of the two bool ("make illegal states unrepresentable"):What do you think?