mirror of
https://github.com/sharkdp/hyperfine.git
synced 2024-10-26 22:21:58 +03:00
Compare commits
6 Commits
e5b98603b8
...
b307d20657
Author | SHA1 | Date | |
---|---|---|---|
|
b307d20657 | ||
|
981db9d102 | ||
|
ef1263279d | ||
|
02975df2ad | ||
|
c83b4126ea | ||
|
4e8cb3fec0 |
@ -54,7 +54,7 @@ fn run_command_and_measure_common(
|
||||
);
|
||||
|
||||
let result = execute_and_measure(command)
|
||||
.with_context(|| format!("Failed to run command '{}'", command_name))?;
|
||||
.with_context(|| format!("Failed to run command '{command_name}'"))?;
|
||||
|
||||
if command_failure_action == CmdFailureAction::RaiseError && !result.status.success() {
|
||||
bail!(
|
||||
@ -62,7 +62,7 @@ fn run_command_and_measure_common(
|
||||
Alternatively, use the '--show-output' option to debug what went wrong.",
|
||||
result.status.code().map_or(
|
||||
"The process has been terminated by a signal".into(),
|
||||
|c| format!("Command terminated with non-zero exit code: {}", c)
|
||||
|c| format!("Command terminated with non-zero exit code: {c}")
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -180,6 +180,7 @@ impl<'a> Executor for ShellExecutor<'a> {
|
||||
COUNT,
|
||||
"Measuring shell spawning time",
|
||||
self.options.output_style,
|
||||
self.options.show_elapsed,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
@ -214,7 +215,8 @@ impl<'a> Executor for ShellExecutor<'a> {
|
||||
}
|
||||
|
||||
if let Some(bar) = progress_bar.as_ref() {
|
||||
bar.inc(1)
|
||||
bar.inc(1);
|
||||
bar.reset_elapsed();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -182,6 +182,7 @@ impl<'a> Benchmark<'a> {
|
||||
self.options.warmup_count,
|
||||
"Performing warmup runs",
|
||||
self.options.output_style,
|
||||
self.options.show_elapsed,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
@ -192,7 +193,8 @@ impl<'a> Benchmark<'a> {
|
||||
let _ = self.executor.run_command_and_measure(self.command, None)?;
|
||||
let _ = run_conclusion_command()?;
|
||||
if let Some(bar) = progress_bar.as_ref() {
|
||||
bar.inc(1)
|
||||
bar.inc(1);
|
||||
bar.reset_elapsed();
|
||||
}
|
||||
}
|
||||
if let Some(bar) = progress_bar.as_ref() {
|
||||
@ -206,6 +208,7 @@ impl<'a> Benchmark<'a> {
|
||||
self.options.run_bounds.min,
|
||||
"Initial time measurement",
|
||||
self.options.output_style,
|
||||
self.options.show_elapsed,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
@ -256,7 +259,8 @@ impl<'a> Benchmark<'a> {
|
||||
bar.set_length(count)
|
||||
}
|
||||
if let Some(bar) = progress_bar.as_ref() {
|
||||
bar.inc(1)
|
||||
bar.inc(1);
|
||||
bar.reset_elapsed();
|
||||
}
|
||||
|
||||
// Gather statistics (perform the actual benchmark)
|
||||
@ -283,7 +287,8 @@ impl<'a> Benchmark<'a> {
|
||||
all_succeeded = all_succeeded && success;
|
||||
|
||||
if let Some(bar) = progress_bar.as_ref() {
|
||||
bar.inc(1)
|
||||
bar.inc(1);
|
||||
bar.reset_elapsed();
|
||||
}
|
||||
|
||||
run_conclusion_command()?;
|
||||
@ -312,7 +317,7 @@ impl<'a> Benchmark<'a> {
|
||||
let (mean_str, time_unit) = format_duration_unit(t_mean, self.options.time_unit);
|
||||
let min_str = format_duration(t_min, Some(time_unit));
|
||||
let max_str = format_duration(t_max, Some(time_unit));
|
||||
let num_str = format!("{} runs", t_num);
|
||||
let num_str = format!("{t_num} runs");
|
||||
|
||||
let user_str = format_duration(user_mean, Some(time_unit));
|
||||
let system_str = format_duration(system_mean, Some(time_unit));
|
||||
|
@ -86,7 +86,7 @@ impl<'a> Scheduler<'a> {
|
||||
"{}{} times faster than {}",
|
||||
format!("{:8.2}", item.relative_speed).bold().green(),
|
||||
if let Some(stddev) = item.relative_speed_stddev {
|
||||
format!(" ± {}", format!("{:.2}", stddev).green())
|
||||
format!(" ± {}", format!("{stddev:.2}").green())
|
||||
} else {
|
||||
"".into()
|
||||
},
|
||||
@ -104,7 +104,7 @@ impl<'a> Scheduler<'a> {
|
||||
if item.is_fastest {
|
||||
" ".into()
|
||||
} else if let Some(stddev) = item.relative_speed_stddev {
|
||||
format!(" ± {}", format!("{:5.2}", stddev).green())
|
||||
format!(" ± {}", format!("{stddev:5.2}").green())
|
||||
} else {
|
||||
" ".into()
|
||||
},
|
||||
|
11
src/cli.rs
11
src/cli.rs
@ -244,6 +244,17 @@ fn build_command() -> Command {
|
||||
* 'mean-time': order benchmarks by mean runtime\n"
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("show-elapsed")
|
||||
.long("show-elapsed")
|
||||
.short('E')
|
||||
.action(ArgAction::SetTrue)
|
||||
.help(
|
||||
"Show time elapsed since the current run was started. \
|
||||
This is useful for especially long benchmarks to see \
|
||||
the progress the benchmark has made"
|
||||
)
|
||||
)
|
||||
.arg(
|
||||
Arg::new("time-unit")
|
||||
.long("time-unit")
|
||||
|
@ -62,13 +62,13 @@ impl<'a> Command<'a> {
|
||||
let parameters = self
|
||||
.get_unused_parameters()
|
||||
.fold(String::new(), |output, (parameter, value)| {
|
||||
output + &format!("{} = {}, ", parameter, value)
|
||||
output + &format!("{parameter} = {value}, ")
|
||||
});
|
||||
let parameters = parameters.trim_end_matches(", ");
|
||||
let parameters = if parameters.is_empty() {
|
||||
"".into()
|
||||
} else {
|
||||
format!(" ({})", parameters)
|
||||
format!(" ({parameters})")
|
||||
};
|
||||
|
||||
format!("{}{}", self.get_name(), parameters)
|
||||
@ -81,7 +81,7 @@ impl<'a> Command<'a> {
|
||||
pub fn get_command(&self) -> Result<std::process::Command> {
|
||||
let command_line = self.get_command_line();
|
||||
let mut tokens = shell_words::split(&command_line)
|
||||
.with_context(|| format!("Failed to parse command '{}'", command_line))?
|
||||
.with_context(|| format!("Failed to parse command '{command_line}'"))?
|
||||
.into_iter();
|
||||
|
||||
if let Some(program_name) = tokens.next() {
|
||||
@ -100,17 +100,14 @@ impl<'a> Command<'a> {
|
||||
pub fn get_unused_parameters(&self) -> impl Iterator<Item = &(&'a str, ParameterValue)> {
|
||||
self.parameters
|
||||
.iter()
|
||||
.filter(move |(parameter, _)| !self.expression.contains(&format!("{{{}}}", parameter)))
|
||||
.filter(move |(parameter, _)| !self.expression.contains(&format!("{{{parameter}}}")))
|
||||
}
|
||||
|
||||
fn replace_parameters_in(&self, original: &str) -> String {
|
||||
let mut result = String::new();
|
||||
let mut replacements = BTreeMap::<String, String>::new();
|
||||
for (param_name, param_value) in &self.parameters {
|
||||
replacements.insert(
|
||||
format!("{{{param_name}}}", param_name = param_name),
|
||||
param_value.to_string(),
|
||||
);
|
||||
replacements.insert(format!("{{{param_name}}}"), param_value.to_string());
|
||||
}
|
||||
let mut remaining = original;
|
||||
// Manually replace consecutive occurrences to avoid double-replacing: e.g.,
|
||||
|
@ -32,7 +32,7 @@ impl MarkupExporter for AsciidocExporter {
|
||||
}
|
||||
|
||||
fn command(&self, cmd: &str) -> String {
|
||||
format!("`{}`", cmd)
|
||||
format!("`{cmd}`")
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,8 +71,7 @@ fn test_asciidoc_exporter_table_header() {
|
||||
#[cfg(test)]
|
||||
fn cfg_test_table_header(unit_short_name: &str) -> String {
|
||||
format!(
|
||||
"[cols=\"<,>,>,>,>\"]\n|===\n| Command \n| Mean [{unit}] \n| Min [{unit}] \n| Max [{unit}] \n| Relative \n",
|
||||
unit = unit_short_name
|
||||
"[cols=\"<,>,>,>,>\"]\n|===\n| Command \n| Mean [{unit_short_name}] \n| Min [{unit_short_name}] \n| Max [{unit_short_name}] \n| Relative \n"
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ impl Exporter for CsvExporter {
|
||||
.collect();
|
||||
if let Some(res) = results.first() {
|
||||
for param_name in res.parameters.keys() {
|
||||
headers.push(Cow::Owned(format!("parameter_{}", param_name).into_bytes()));
|
||||
headers.push(Cow::Owned(format!("parameter_{param_name}").into_bytes()));
|
||||
}
|
||||
}
|
||||
writer.write_record(headers)?;
|
||||
|
@ -24,7 +24,7 @@ impl MarkupExporter for MarkdownExporter {
|
||||
}
|
||||
|
||||
fn command(&self, cmd: &str) -> String {
|
||||
format!("`{}`", cmd)
|
||||
format!("`{cmd}`")
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,8 +53,7 @@ fn test_markdown_formatter_table_divider() {
|
||||
#[cfg(test)]
|
||||
fn cfg_test_table_header(unit_short_name: String) -> String {
|
||||
format!(
|
||||
"| Command | Mean [{unit}] | Min [{unit}] | Max [{unit}] | Relative |\n|:---|---:|---:|---:|---:|\n",
|
||||
unit = unit_short_name
|
||||
"| Command | Mean [{unit_short_name}] | Min [{unit_short_name}] | Max [{unit_short_name}] | Relative |\n|:---|---:|---:|---:|---:|\n"
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -32,9 +32,9 @@ pub trait MarkupExporter {
|
||||
// emit table header data
|
||||
table.push_str(&self.table_row(&[
|
||||
"Command",
|
||||
&format!("Mean {}", notation),
|
||||
&format!("Min {}", notation),
|
||||
&format!("Max {}", notation),
|
||||
&format!("Mean {notation}"),
|
||||
&format!("Min {notation}"),
|
||||
&format!("Max {notation}"),
|
||||
"Relative",
|
||||
]));
|
||||
|
||||
@ -59,7 +59,7 @@ pub trait MarkupExporter {
|
||||
let rel_stddev_str = if entry.is_fastest {
|
||||
"".into()
|
||||
} else if let Some(stddev) = entry.relative_speed_stddev {
|
||||
format!(" ± {:.2}", stddev)
|
||||
format!(" ± {stddev:.2}")
|
||||
} else {
|
||||
"".into()
|
||||
};
|
||||
@ -67,10 +67,10 @@ pub trait MarkupExporter {
|
||||
// prepare table row entries
|
||||
table.push_str(&self.table_row(&[
|
||||
&self.command(&cmd_str),
|
||||
&format!("{}{}", mean_str, stddev_str),
|
||||
&format!("{mean_str}{stddev_str}"),
|
||||
&min_str,
|
||||
&max_str,
|
||||
&format!("{}{}", rel_str, rel_stddev_str),
|
||||
&format!("{rel_str}{rel_stddev_str}"),
|
||||
]))
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,7 @@ impl ExportManager {
|
||||
ExportTarget::Stdout
|
||||
} else {
|
||||
let _ = File::create(filename)
|
||||
.with_context(|| format!("Could not create export file '{}'", filename))?;
|
||||
.with_context(|| format!("Could not create export file '{filename}'"))?;
|
||||
ExportTarget::File(filename.to_string())
|
||||
},
|
||||
});
|
||||
@ -153,5 +153,5 @@ impl ExportManager {
|
||||
fn write_to_file(filename: &str, content: &[u8]) -> Result<()> {
|
||||
let mut file = OpenOptions::new().write(true).open(filename)?;
|
||||
file.write_all(content)
|
||||
.with_context(|| format!("Failed to export results to '{}'", filename))
|
||||
.with_context(|| format!("Failed to export results to '{filename}'"))
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ impl MarkupExporter for OrgmodeExporter {
|
||||
}
|
||||
|
||||
fn command(&self, cmd: &str) -> String {
|
||||
format!("={}=", cmd)
|
||||
format!("={cmd}=")
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,8 +58,7 @@ fn test_orgmode_formatter_table_line() {
|
||||
#[cfg(test)]
|
||||
fn cfg_test_table_header(unit_short_name: String) -> String {
|
||||
format!(
|
||||
"| Command | Mean [{unit}] | Min [{unit}] | Max [{unit}] | Relative |\n|--+--+--+--+--|\n",
|
||||
unit = unit_short_name
|
||||
"| Command | Mean [{unit_short_name}] | Min [{unit_short_name}] | Max [{unit_short_name}] | Relative |\n|--+--+--+--+--|\n"
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ impl Default for Shell {
|
||||
impl fmt::Display for Shell {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Shell::Default(cmd) => write!(f, "{}", cmd),
|
||||
Shell::Default(cmd) => write!(f, "{cmd}"),
|
||||
Shell::Custom(cmdline) => write!(f, "{}", shell_words::join(cmdline)),
|
||||
}
|
||||
}
|
||||
@ -236,6 +236,9 @@ pub struct Options {
|
||||
|
||||
/// Which time unit to use when displaying results
|
||||
pub time_unit: Option<Unit>,
|
||||
|
||||
/// Show elapsed time since current run start.
|
||||
pub show_elapsed: bool,
|
||||
}
|
||||
|
||||
impl Default for Options {
|
||||
@ -256,6 +259,7 @@ impl Default for Options {
|
||||
command_output_policy: CommandOutputPolicy::Null,
|
||||
time_unit: None,
|
||||
command_input_policy: CommandInputPolicy::Null,
|
||||
show_elapsed: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -427,6 +431,10 @@ impl Options {
|
||||
CommandInputPolicy::Null
|
||||
};
|
||||
|
||||
if matches.get_flag("show-elapsed") {
|
||||
options.show_elapsed = true;
|
||||
}
|
||||
|
||||
Ok(options)
|
||||
}
|
||||
|
||||
@ -457,7 +465,7 @@ impl Options {
|
||||
fn test_default_shell() {
|
||||
let shell = Shell::default();
|
||||
|
||||
let s = format!("{}", shell);
|
||||
let s = format!("{shell}");
|
||||
assert_eq!(&s, DEFAULT_SHELL);
|
||||
|
||||
let cmd = shell.command();
|
||||
@ -468,7 +476,7 @@ fn test_default_shell() {
|
||||
fn test_can_parse_shell_command_line_from_str() {
|
||||
let shell = Shell::parse_from_str("shell -x 'aaa bbb'").unwrap();
|
||||
|
||||
let s = format!("{}", shell);
|
||||
let s = format!("{shell}");
|
||||
assert_eq!(&s, "shell -x 'aaa bbb'");
|
||||
|
||||
let cmd = shell.command();
|
||||
|
@ -10,12 +10,22 @@ const TICK_SETTINGS: (&str, u64) = ("⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏ ", 80);
|
||||
const TICK_SETTINGS: (&str, u64) = (r"+-x| ", 200);
|
||||
|
||||
/// Return a pre-configured progress bar
|
||||
pub fn get_progress_bar(length: u64, msg: &str, option: OutputStyleOption) -> ProgressBar {
|
||||
pub fn get_progress_bar(
|
||||
length: u64,
|
||||
msg: &str,
|
||||
option: OutputStyleOption,
|
||||
show_elapsed: bool,
|
||||
) -> ProgressBar {
|
||||
let template_str = match show_elapsed {
|
||||
true => " {spinner} {msg:<30} {wide_bar} ET {elapsed_precise} ETA {eta_precise} ",
|
||||
false => " {spinner} {msg:<30} {wide_bar} ETA {eta_precise} ",
|
||||
};
|
||||
|
||||
let progressbar_style = match option {
|
||||
OutputStyleOption::Basic | OutputStyleOption::Color => ProgressStyle::default_bar(),
|
||||
_ => ProgressStyle::default_spinner()
|
||||
.tick_chars(TICK_SETTINGS.0)
|
||||
.template(" {spinner} {msg:<30} {wide_bar} ETA {eta_precise} ")
|
||||
.template(template_str)
|
||||
.expect("no template error"),
|
||||
};
|
||||
|
||||
|
@ -16,7 +16,7 @@ impl Display for ParameterValue {
|
||||
ParameterValue::Text(ref value) => value.clone(),
|
||||
ParameterValue::Numeric(value) => value.to_string(),
|
||||
};
|
||||
write!(f, "{}", str)
|
||||
write!(f, "{str}")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ impl Unit {
|
||||
/// Returns the Second value formatted for the Unit.
|
||||
pub fn format(self, value: Second) -> String {
|
||||
match self {
|
||||
Unit::Second => format!("{:.3}", value),
|
||||
Unit::Second => format!("{value:.3}"),
|
||||
Unit::MilliSecond => format!("{:.1}", value * 1e3),
|
||||
Unit::MicroSecond => format!("{:.1}", value * 1e6),
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user