mirror of
https://github.com/sharkdp/hyperfine.git
synced 2026-11-01 08:50:19 +00:00
Do not export intermediate results to stdout, closes #640
This commit is contained in:
1 parent
d2fb7d4c4c
commit
2793d7b994
4 files changed
+50
-22
No files matched your search
@@ -44,10 +44,9 @@ impl<'a> Scheduler<'a> {
|
|||||||
self.results
|
self.results
|
||||||
.push(Benchmark::new(number, cmd, self.options, &*executor).run()?);
|
.push(Benchmark::new(number, cmd, self.options, &*executor).run()?);
|
||||||
|
|
||||||
// We export (all results so far) after each individual benchmark, because
|
// We export results after each individual benchmark, because
|
||||||
// we would risk losing all results if a later benchmark fails.
|
// we would risk losing them if a later benchmark fails.
|
||||||
self.export_manager
|
self.export_manager.write_results(&self.results, true)?;
|
||||||
.write_results(&self.results, self.options.time_unit)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -94,4 +93,8 @@ impl<'a> Scheduler<'a> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn final_export(&self) -> Result<()> {
|
||||||
|
self.export_manager.write_results(&self.results, false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -10,6 +10,7 @@ pub enum Alignment {
|
|||||||
Left,
|
Left,
|
||||||
Right,
|
Right,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait MarkupExporter {
|
pub trait MarkupExporter {
|
||||||
fn table_results(&self, entries: &[BenchmarkResultWithRelativeSpeed], unit: Unit) -> String {
|
fn table_results(&self, entries: &[BenchmarkResultWithRelativeSpeed], unit: Unit) -> String {
|
||||||
// prepare table header strings
|
// prepare table header strings
|
||||||
|
|||||||
+40
-17
@@ -45,22 +45,31 @@ trait Exporter {
|
|||||||
fn serialize(&self, results: &[BenchmarkResult], unit: Option<Unit>) -> Result<Vec<u8>>;
|
fn serialize(&self, results: &[BenchmarkResult], unit: Option<Unit>) -> Result<Vec<u8>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ExporterWithFilename {
|
pub enum ExportTarget {
|
||||||
|
File(String),
|
||||||
|
Stdout,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ExporterWithTarget {
|
||||||
exporter: Box<dyn Exporter>,
|
exporter: Box<dyn Exporter>,
|
||||||
filename: String,
|
target: ExportTarget,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handles the management of multiple file exporters.
|
/// Handles the management of multiple file exporters.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct ExportManager {
|
pub struct ExportManager {
|
||||||
exporters: Vec<ExporterWithFilename>,
|
exporters: Vec<ExporterWithTarget>,
|
||||||
|
time_unit: Option<Unit>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExportManager {
|
impl ExportManager {
|
||||||
/// Build the ExportManager that will export the results specified
|
/// Build the ExportManager that will export the results specified
|
||||||
/// in the given ArgMatches
|
/// in the given ArgMatches
|
||||||
pub fn from_cli_arguments(matches: &ArgMatches) -> Result<Self> {
|
pub fn from_cli_arguments(matches: &ArgMatches, time_unit: Option<Unit>) -> Result<Self> {
|
||||||
let mut export_manager = Self::default();
|
let mut export_manager = Self {
|
||||||
|
exporters: vec![],
|
||||||
|
time_unit,
|
||||||
|
};
|
||||||
{
|
{
|
||||||
let mut add_exporter = |flag, exporttype| -> Result<()> {
|
let mut add_exporter = |flag, exporttype| -> Result<()> {
|
||||||
if let Some(filename) = matches.get_one::<String>(flag) {
|
if let Some(filename) = matches.get_one::<String>(flag) {
|
||||||
@@ -87,29 +96,43 @@ impl ExportManager {
|
|||||||
ExportType::Orgmode => Box::<OrgmodeExporter>::default(),
|
ExportType::Orgmode => Box::<OrgmodeExporter>::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.exporters.push(ExporterWithFilename {
|
self.exporters.push(ExporterWithTarget {
|
||||||
exporter,
|
exporter,
|
||||||
filename: if filename == "-" {
|
target: if filename == "-" {
|
||||||
if cfg!(windows) {
|
ExportTarget::Stdout
|
||||||
"con:".to_string()
|
|
||||||
} else {
|
|
||||||
"/dev/stdout".to_string()
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
let _ = File::create(filename)
|
let _ = File::create(filename)
|
||||||
.with_context(|| format!("Could not create export file '{}'", filename))?;
|
.with_context(|| format!("Could not create export file '{}'", filename))?;
|
||||||
filename.to_string()
|
ExportTarget::File(filename.to_string())
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write the given results to all Exporters contained within this manager
|
/// Write the given results to all Exporters. The 'intermediate' flag specifies
|
||||||
pub fn write_results(&self, results: &[BenchmarkResult], unit: Option<Unit>) -> Result<()> {
|
/// whether this is being called while still performing benchmarks, or if this
|
||||||
|
/// is the final call after all benchmarks have been finished. In the former case,
|
||||||
|
/// results are written to all file targets (to always have them up to date, even
|
||||||
|
/// if a benchmark fails). In the latter case, we only print to stdout targets (in
|
||||||
|
/// order not to clutter the output of hyperfine with intermediate results).
|
||||||
|
pub fn write_results(&self, results: &[BenchmarkResult], intermediate: bool) -> Result<()> {
|
||||||
for e in &self.exporters {
|
for e in &self.exporters {
|
||||||
let file_content = e.exporter.serialize(results, unit)?;
|
let content = || e.exporter.serialize(results, self.time_unit);
|
||||||
write_to_file(&e.filename, &file_content)?;
|
|
||||||
|
match e.target {
|
||||||
|
ExportTarget::File(ref filename) => {
|
||||||
|
if intermediate {
|
||||||
|
write_to_file(filename, &content()?)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ExportTarget::Stdout => {
|
||||||
|
if !intermediate {
|
||||||
|
println!();
|
||||||
|
println!("{}", String::from_utf8(content()?).unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -34,13 +34,14 @@ fn run() -> Result<()> {
|
|||||||
let cli_arguments = get_cli_arguments(env::args_os());
|
let cli_arguments = get_cli_arguments(env::args_os());
|
||||||
let options = Options::from_cli_arguments(&cli_arguments)?;
|
let options = Options::from_cli_arguments(&cli_arguments)?;
|
||||||
let commands = Commands::from_cli_arguments(&cli_arguments)?;
|
let commands = Commands::from_cli_arguments(&cli_arguments)?;
|
||||||
let export_manager = ExportManager::from_cli_arguments(&cli_arguments)?;
|
let export_manager = ExportManager::from_cli_arguments(&cli_arguments, options.time_unit)?;
|
||||||
|
|
||||||
options.validate_against_command_list(&commands)?;
|
options.validate_against_command_list(&commands)?;
|
||||||
|
|
||||||
let mut scheduler = Scheduler::new(&commands, &options, &export_manager);
|
let mut scheduler = Scheduler::new(&commands, &options, &export_manager);
|
||||||
scheduler.run_benchmarks()?;
|
scheduler.run_benchmarks()?;
|
||||||
scheduler.print_relative_speed_comparison();
|
scheduler.print_relative_speed_comparison();
|
||||||
|
scheduler.final_export()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user