mirror of
https://github.com/sharkdp/hyperfine.git
synced 2026-11-01 08:50:19 +00:00
Add option to set the shell, closes #61
Allow the user to set the shell used for executing benchmark commands. The option (-S/--shell) can be overridden, when there are duplicate options the last option's value will be used.
This commit is contained in:
1 parent
0b18446c0c
commit
01581f60e0
5 files changed
+55
-20
No files matched your search
@@ -109,6 +109,15 @@ fn build_app() -> App<'static, 'static> {
|
||||
the colors without any interactive output.",
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("shell")
|
||||
.long("shell")
|
||||
.short("S")
|
||||
.takes_value(true)
|
||||
.value_name("SHELL")
|
||||
.overrides_with("shell")
|
||||
.help("Set the shell to use (default: sh) for executing benchmarked commands."),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("ignore-failure")
|
||||
.long("ignore-failure")
|
||||
|
||||
@@ -39,6 +39,7 @@ fn subtract_shell_spawning_time(time: Second, shell_spawning_time: Second) -> Se
|
||||
|
||||
/// Run the given shell command and measure the execution time
|
||||
pub fn time_shell_command(
|
||||
shell: &str,
|
||||
command: &Command,
|
||||
show_output: bool,
|
||||
failure_action: CmdFailureAction,
|
||||
@@ -51,7 +52,7 @@ pub fn time_shell_command(
|
||||
} else {
|
||||
(Stdio::null(), Stdio::null())
|
||||
};
|
||||
let result = execute_and_time(stdout, stderr, &command.get_shell_command())?;
|
||||
let result = execute_and_time(stdout, stderr, &command.get_shell_command(), shell)?;
|
||||
|
||||
let mut time_user = result.user_time;
|
||||
let mut time_system = result.system_time;
|
||||
@@ -86,6 +87,7 @@ pub fn time_shell_command(
|
||||
|
||||
/// Measure the average shell spawning time
|
||||
pub fn mean_shell_spawning_time(
|
||||
shell: &str,
|
||||
style: &OutputStyleOption,
|
||||
show_output: bool,
|
||||
) -> io::Result<TimingResult> {
|
||||
@@ -99,6 +101,7 @@ pub fn mean_shell_spawning_time(
|
||||
for _ in 0..COUNT {
|
||||
// Just run the shell without any command
|
||||
let res = time_shell_command(
|
||||
shell,
|
||||
&Command::new(""),
|
||||
show_output,
|
||||
CmdFailureAction::RaiseError,
|
||||
@@ -107,11 +110,17 @@ pub fn mean_shell_spawning_time(
|
||||
|
||||
match res {
|
||||
Err(_) => {
|
||||
let shell_cmd = if cfg!(windows) {
|
||||
format!("{} /C \"\"", shell)
|
||||
} else {
|
||||
format!("{} -c \"\"", shell)
|
||||
};
|
||||
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"Could not measure shell execution time. \
|
||||
Make sure you can run 'sh -c \"\"'.",
|
||||
))
|
||||
io::ErrorKind::Other,
|
||||
format!("Could not measure shell execution time. \
|
||||
Make sure you can run '{}'.", shell_cmd),
|
||||
))
|
||||
}
|
||||
Ok((r, _)) => {
|
||||
times_real.push(r.time_real);
|
||||
@@ -132,11 +141,12 @@ pub fn mean_shell_spawning_time(
|
||||
|
||||
/// Run the command specified by `--prepare`.
|
||||
fn run_preparation_command(
|
||||
shell: &str,
|
||||
command: &Option<Command>,
|
||||
show_output: bool,
|
||||
) -> io::Result<TimingResult> {
|
||||
if let &Some(ref cmd) = command {
|
||||
let res = time_shell_command(cmd, show_output, CmdFailureAction::RaiseError, None);
|
||||
let res = time_shell_command(shell, cmd, show_output, CmdFailureAction::RaiseError, None);
|
||||
if res.is_err() {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
@@ -179,7 +189,7 @@ pub fn run_benchmark(
|
||||
);
|
||||
|
||||
for _ in 0..options.warmup_count {
|
||||
let _ = time_shell_command(cmd, options.show_output, options.failure_action, None)?;
|
||||
let _ = time_shell_command(&options.shell, cmd, options.show_output, options.failure_action, None)?;
|
||||
progress_bar.inc(1);
|
||||
}
|
||||
progress_bar.finish_and_clear();
|
||||
@@ -200,10 +210,11 @@ pub fn run_benchmark(
|
||||
Some((param, value)) => Command::new_parametrized(preparation_command, param, value),
|
||||
None => Command::new(preparation_command),
|
||||
});
|
||||
let prepare_res = run_preparation_command(&prepare_cmd, options.show_output)?;
|
||||
let prepare_res = run_preparation_command(&options.shell, &prepare_cmd, options.show_output)?;
|
||||
|
||||
// Initial timing run
|
||||
let (res, success) = time_shell_command(
|
||||
&options.shell,
|
||||
cmd,
|
||||
options.show_output,
|
||||
options.failure_action,
|
||||
@@ -240,7 +251,7 @@ pub fn run_benchmark(
|
||||
|
||||
// Gather statistics
|
||||
for _ in 0..count_remaining {
|
||||
run_preparation_command(&prepare_cmd, options.show_output)?;
|
||||
run_preparation_command(&options.shell, &prepare_cmd, options.show_output)?;
|
||||
|
||||
let msg = {
|
||||
let mean = format_duration(mean(×_real), None);
|
||||
@@ -249,6 +260,7 @@ pub fn run_benchmark(
|
||||
progress_bar.set_message(&msg);
|
||||
|
||||
let (res, success) = time_shell_command(
|
||||
&options.shell,
|
||||
cmd,
|
||||
options.show_output,
|
||||
options.failure_action,
|
||||
|
||||
+10
-8
@@ -19,8 +19,8 @@ pub struct ExecuteResult {
|
||||
|
||||
/// Execute the given command and return a timing summary
|
||||
#[cfg(windows)]
|
||||
pub fn execute_and_time(stdout: Stdio, stderr: Stdio, command: &str) -> io::Result<ExecuteResult> {
|
||||
let mut child = run_shell_command(stdout, stderr, command)?;
|
||||
pub fn execute_and_time(stdout: Stdio, stderr: Stdio, command: &str, shell: &str) -> io::Result<ExecuteResult> {
|
||||
let mut child = run_shell_command(stdout, stderr, command, shell)?;
|
||||
let cpu_timer = get_cpu_timer(&child);
|
||||
let status = child.wait()?;
|
||||
|
||||
@@ -34,10 +34,10 @@ pub fn execute_and_time(stdout: Stdio, stderr: Stdio, command: &str) -> io::Resu
|
||||
|
||||
/// Execute the given command and return a timing summary
|
||||
#[cfg(not(windows))]
|
||||
pub fn execute_and_time(stdout: Stdio, stderr: Stdio, command: &str) -> io::Result<ExecuteResult> {
|
||||
pub fn execute_and_time(stdout: Stdio, stderr: Stdio, command: &str, shell: &str) -> io::Result<ExecuteResult> {
|
||||
let cpu_timer = get_cpu_timer();
|
||||
|
||||
let status = run_shell_command(stdout, stderr, command)?;
|
||||
let status = run_shell_command(stdout, stderr, command, shell)?;
|
||||
|
||||
let (user_time, system_time) = cpu_timer.stop();
|
||||
|
||||
@@ -48,14 +48,15 @@ pub fn execute_and_time(stdout: Stdio, stderr: Stdio, command: &str) -> io::Resu
|
||||
})
|
||||
}
|
||||
|
||||
/// Run a standard shell command
|
||||
/// Run a standard shell command using `sh -c`
|
||||
#[cfg(not(windows))]
|
||||
fn run_shell_command(
|
||||
stdout: Stdio,
|
||||
stderr: Stdio,
|
||||
command: &str,
|
||||
shell: &str,
|
||||
) -> io::Result<std::process::ExitStatus> {
|
||||
Command::new("sh")
|
||||
Command::new(shell)
|
||||
.arg("-c")
|
||||
.arg(command)
|
||||
.stdin(Stdio::null())
|
||||
@@ -64,14 +65,15 @@ fn run_shell_command(
|
||||
.status()
|
||||
}
|
||||
|
||||
/// Run a Windows shell command using cmd.exe
|
||||
/// Run a Windows shell command using `cmd.exe /C`
|
||||
#[cfg(windows)]
|
||||
fn run_shell_command(
|
||||
stdout: Stdio,
|
||||
stderr: Stdio,
|
||||
command: &str,
|
||||
shell: &str,
|
||||
) -> io::Result<std::process::Child> {
|
||||
Command::new("cmd.exe")
|
||||
Command::new(shell)
|
||||
.arg("/C")
|
||||
.arg(command)
|
||||
.stdin(Stdio::null())
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
/// This module contains common internal types.
|
||||
use std::fmt;
|
||||
|
||||
#[cfg(not(windows))]
|
||||
pub const DEFAULT_SHELL: &str = "sh";
|
||||
|
||||
#[cfg(windows)]
|
||||
pub const DEFAULT_SHELL: &str = "cmd.exe";
|
||||
|
||||
/// Type alias for unit of time
|
||||
pub type Second = f64;
|
||||
|
||||
@@ -111,6 +117,9 @@ pub struct HyperfineOptions {
|
||||
/// What color mode to use for output
|
||||
pub output_style: OutputStyleOption,
|
||||
|
||||
/// The shell to use for executing commands.
|
||||
pub shell: String,
|
||||
|
||||
/// Forward benchmark's stdout to hyperfine's stdout
|
||||
pub show_output: bool,
|
||||
}
|
||||
@@ -124,6 +133,7 @@ impl Default for HyperfineOptions {
|
||||
failure_action: CmdFailureAction::RaiseError,
|
||||
preparation_command: None,
|
||||
output_style: OutputStyleOption::Full,
|
||||
shell: DEFAULT_SHELL.to_string(),
|
||||
show_output: false,
|
||||
}
|
||||
}
|
||||
|
||||
+5
-3
@@ -57,7 +57,7 @@ pub fn error(message: &str) -> ! {
|
||||
|
||||
/// Runs the benchmark for the given commands
|
||||
fn run(commands: &Vec<Command>, options: &HyperfineOptions) -> io::Result<Vec<BenchmarkResult>> {
|
||||
let shell_spawning_time = mean_shell_spawning_time(&options.output_style, options.show_output)?;
|
||||
let shell_spawning_time = mean_shell_spawning_time(&options.shell, &options.output_style, options.show_output)?;
|
||||
|
||||
let mut timing_results = vec![];
|
||||
|
||||
@@ -123,7 +123,7 @@ fn build_hyperfine_options(matches: &ArgMatches) -> Result<HyperfineOptions, Opt
|
||||
options.warmup_count = matches
|
||||
.value_of("warmup")
|
||||
.and_then(&str_to_u64)
|
||||
.unwrap_or(0);
|
||||
.unwrap_or(options.warmup_count);
|
||||
|
||||
let mut min_runs = matches.value_of("min-runs").and_then(&str_to_u64);
|
||||
let mut max_runs = matches.value_of("max-runs").and_then(&str_to_u64);
|
||||
@@ -188,7 +188,9 @@ fn build_hyperfine_options(matches: &ArgMatches) -> Result<HyperfineOptions, Opt
|
||||
colored::control::set_override(false)
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
};
|
||||
|
||||
options.shell = matches.value_of("shell").unwrap_or(&options.shell).to_string();
|
||||
|
||||
if matches.is_present("ignore-failure") {
|
||||
options.failure_action = CmdFailureAction::Ignore;
|
||||
|
||||
Reference in new issue
Block a user