From 0ebd76dfc2e630304f8e0255e753602a3af86a0c Mon Sep 17 00:00:00 2001 From: David Peter Date: Sun, 20 Feb 2022 13:15:54 +0100 Subject: [PATCH] Turn show_output into enum --- src/benchmark/mod.rs | 66 ++++++++++++++++++++++---------------- src/benchmark/scheduler.rs | 2 +- src/options.rs | 62 +++++++++++++++++++++++------------ 3 files changed, 81 insertions(+), 49 deletions(-) diff --git a/src/benchmark/mod.rs b/src/benchmark/mod.rs index a262976..e2b6f6f 100644 --- a/src/benchmark/mod.rs +++ b/src/benchmark/mod.rs @@ -10,7 +10,7 @@ use statistical::{mean, median, standard_deviation}; use crate::benchmark::result::BenchmarkResult; use crate::command::Command; -use crate::options::{CmdFailureAction, Options, OutputStyleOption, Shell}; +use crate::options::{CmdFailureAction, CommandOutputPolicy, Options, OutputStyleOption, Shell}; use crate::outlier_detection::{modified_zscores, OUTLIER_THRESHOLD}; use crate::output::format::{format_duration, format_duration_unit}; use crate::output::progress_bar::get_progress_bar; @@ -52,14 +52,13 @@ fn subtract_shell_spawning_time(time: Second, shell_spawning_time: Second) -> Se pub fn time_shell_command( shell: &Shell, command: &Command<'_>, - show_output: bool, + command_output_policy: CommandOutputPolicy, failure_action: CmdFailureAction, shell_spawning_time: Option, ) -> Result<(TimingResult, ExitStatus)> { - let (stdout, stderr) = if show_output { - (Stdio::inherit(), Stdio::inherit()) - } else { - (Stdio::null(), Stdio::null()) + let (stdout, stderr) = match command_output_policy { + CommandOutputPolicy::Discard => (Stdio::null(), Stdio::null()), + CommandOutputPolicy::Forward => (Stdio::inherit(), Stdio::inherit()), }; let wallclock_timer = WallClockTimer::start(); @@ -101,7 +100,7 @@ pub fn time_shell_command( pub fn mean_shell_spawning_time( shell: &Shell, style: OutputStyleOption, - show_output: bool, + command_output_policy: CommandOutputPolicy, ) -> Result { const COUNT: u64 = 50; let progress_bar = if style != OutputStyleOption::Disabled { @@ -123,7 +122,7 @@ pub fn mean_shell_spawning_time( let res = time_shell_command( shell, &Command::new(None, ""), - show_output, + command_output_policy, CmdFailureAction::RaiseError, None, ); @@ -167,11 +166,17 @@ pub fn mean_shell_spawning_time( fn run_intermediate_command( shell: &Shell, command: &Option>, - show_output: bool, + command_output_policy: CommandOutputPolicy, error_output: &'static str, ) -> Result { if let Some(ref cmd) = command { - let res = time_shell_command(shell, cmd, show_output, CmdFailureAction::RaiseError, None); + let res = time_shell_command( + shell, + cmd, + command_output_policy, + CmdFailureAction::RaiseError, + None, + ); if res.is_err() { bail!(error_output); } @@ -186,36 +191,36 @@ fn run_intermediate_command( fn run_setup_command( shell: &Shell, command: &Option>, - show_output: bool, + output_policy: CommandOutputPolicy, ) -> Result { let error_output = "The setup command terminated with a non-zero exit code. \ Append ' || true' to the command if you are sure that this can be ignored."; - run_intermediate_command(shell, command, show_output, error_output) + run_intermediate_command(shell, command, output_policy, error_output) } /// Run the command specified by `--prepare`. fn run_preparation_command( shell: &Shell, command: &Option>, - show_output: bool, + output_policy: CommandOutputPolicy, ) -> Result { let error_output = "The preparation command terminated with a non-zero exit code. \ Append ' || true' to the command if you are sure that this can be ignored."; - run_intermediate_command(shell, command, show_output, error_output) + run_intermediate_command(shell, command, output_policy, error_output) } /// Run the command specified by `--cleanup`. fn run_cleanup_command( shell: &Shell, command: &Option>, - show_output: bool, + output_policy: CommandOutputPolicy, ) -> Result { let error_output = "The cleanup command terminated with a non-zero exit code. \ Append ' || true' to the command if you are sure that this can be ignored."; - run_intermediate_command(shell, command, show_output, error_output) + run_intermediate_command(shell, command, output_policy, error_output) } #[cfg(unix)] @@ -276,7 +281,7 @@ pub fn run_benchmark( let setup_cmd = options.setup_command.as_ref().map(|setup_command| { Command::new_parametrized(None, setup_command, cmd.get_parameters().clone()) }); - run_setup_command(&options.shell, &setup_cmd, options.show_output)?; + run_setup_command(&options.shell, &setup_cmd, options.command_output_policy)?; // Warmup phase if options.warmup_count > 0 { @@ -291,12 +296,16 @@ pub fn run_benchmark( }; for _ in 0..options.warmup_count { - let _ = run_preparation_command(&options.shell, &prepare_cmd, options.show_output)?; + let _ = run_preparation_command( + &options.shell, + &prepare_cmd, + options.command_output_policy, + )?; let _ = time_shell_command( &options.shell, cmd, - options.show_output, - options.failure_action, + options.command_output_policy, + options.command_failure_action, None, )?; if let Some(bar) = progress_bar.as_ref() { @@ -319,20 +328,21 @@ pub fn run_benchmark( None }; - let prepare_result = run_preparation_command(&options.shell, &prepare_cmd, options.show_output)?; + let prepare_result = + run_preparation_command(&options.shell, &prepare_cmd, options.command_output_policy)?; // Initial timing run let (res, status) = time_shell_command( &options.shell, cmd, - options.show_output, - options.failure_action, + options.command_output_policy, + options.command_failure_action, Some(shell_spawning_time), )?; let success = status.success(); // Determine number of benchmark runs - let runs_in_min_time = (options.min_time_sec + let runs_in_min_time = (options.min_benchmarking_time / (res.time_real + prepare_result.time_real + shell_spawning_time.time_real)) as u64; @@ -367,7 +377,7 @@ pub fn run_benchmark( // Gather statistics for _ in 0..count_remaining { - run_preparation_command(&options.shell, &prepare_cmd, options.show_output)?; + run_preparation_command(&options.shell, &prepare_cmd, options.command_output_policy)?; let msg = { let mean = format_duration(mean(×_real), options.time_unit); @@ -381,8 +391,8 @@ pub fn run_benchmark( let (res, status) = time_shell_command( &options.shell, cmd, - options.show_output, - options.failure_action, + options.command_output_policy, + options.command_failure_action, Some(shell_spawning_time), )?; let success = status.success(); @@ -498,7 +508,7 @@ pub fn run_benchmark( let cleanup_cmd = options.cleanup_command.as_ref().map(|cleanup_command| { Command::new_parametrized(None, cleanup_command, cmd.get_parameters().clone()) }); - run_cleanup_command(&options.shell, &cleanup_cmd, options.show_output)?; + run_cleanup_command(&options.shell, &cleanup_cmd, options.command_output_policy)?; Ok(BenchmarkResult { command: command_name, diff --git a/src/benchmark/scheduler.rs b/src/benchmark/scheduler.rs index ca950c4..6e92ce1 100644 --- a/src/benchmark/scheduler.rs +++ b/src/benchmark/scheduler.rs @@ -32,7 +32,7 @@ impl<'a> Scheduler<'a> { let shell_spawning_time = mean_shell_spawning_time( &self.options.shell, self.options.output_style, - self.options.show_output, + self.options.command_output_policy, )?; for (num, cmd) in self.commands.iter().enumerate() { diff --git a/src/options.rs b/src/options.rs index e385e81..5c060eb 100644 --- a/src/options.rs +++ b/src/options.rs @@ -103,42 +103,58 @@ pub struct RunBounds { } impl Default for RunBounds { - fn default() -> RunBounds { + fn default() -> Self { RunBounds { min: 10, max: None } } } -/// A set of options for hyperfine -pub struct Options { - /// Number of warmup runs - pub warmup_count: u64, +/// How to handle the output of benchmarked commands +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum CommandOutputPolicy { + /// Discard all output + Discard, + /// Show command output on the terminal + Forward, +} + +impl Default for CommandOutputPolicy { + fn default() -> Self { + CommandOutputPolicy::Discard + } +} + +/// The main settings for a hyperfine benchmark session +pub struct Options { /// Upper and lower bound for the number of benchmark runs pub run_bounds: RunBounds, + /// Number of warmup runs + pub warmup_count: u64, + /// Minimum benchmarking time - pub min_time_sec: Second, + pub min_benchmarking_time: Second, /// Whether or not to ignore non-zero exit codes - pub failure_action: CmdFailureAction, - - /// Command to run before each batch of timing runs - pub setup_command: Option, + pub command_failure_action: CmdFailureAction, /// Command to run before each timing run pub preparation_command: Option>, - /// Command to run after each benchmark + /// Command to run before each *batch* of timing runs, i.e. before each individual benchmark + pub setup_command: Option, + + /// Command to run after each *batch* of timing runs, i.e. after each individual benchmark pub cleanup_command: Option, - /// What color mode to use for output + /// What color mode to use for the terminal output pub output_style: OutputStyleOption, /// The shell to use for executing commands. pub shell: Shell, - /// Forward benchmark's stdout to hyperfine's stdout - pub show_output: bool, + /// What to do with the output of the benchmarked command + pub command_output_policy: CommandOutputPolicy, /// Which time unit to use for CLI & Markdown output pub time_unit: Option, @@ -155,14 +171,14 @@ impl Default for Options { names: None, warmup_count: 0, run_bounds: RunBounds::default(), - min_time_sec: 3.0, - failure_action: CmdFailureAction::RaiseError, + min_benchmarking_time: 3.0, + command_failure_action: CmdFailureAction::RaiseError, setup_command: None, preparation_command: None, cleanup_command: None, output_style: OutputStyleOption::Full, shell: Shell::default(), - show_output: false, + command_output_policy: CommandOutputPolicy::Discard, time_unit: None, } } @@ -218,7 +234,11 @@ impl Options { options.cleanup_command = matches.value_of("cleanup").map(String::from); - options.show_output = matches.is_present("show-output"); + options.command_output_policy = if matches.is_present("show-output") { + CommandOutputPolicy::Forward + } else { + CommandOutputPolicy::Discard + }; options.output_style = match matches.value_of("style") { Some("full") => OutputStyleOption::Full, @@ -227,7 +247,9 @@ impl Options { Some("color") => OutputStyleOption::Color, Some("none") => OutputStyleOption::Disabled, _ => { - if !options.show_output && atty::is(Stream::Stdout) { + if options.command_output_policy == CommandOutputPolicy::Discard + && atty::is(Stream::Stdout) + { OutputStyleOption::Full } else { OutputStyleOption::Basic @@ -250,7 +272,7 @@ impl Options { } if matches.is_present("ignore-failure") { - options.failure_action = CmdFailureAction::Ignore; + options.command_failure_action = CmdFailureAction::Ignore; } options.time_unit = match matches.value_of("time-unit") {