Skip to content

Commit

Permalink
Do not export intermediate results to stdout, closes #640
Browse files Browse the repository at this point in the history
  • Loading branch information
sharkdp committed Apr 20, 2023
1 parent d2fb7d4 commit 2793d7b
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 22 deletions.
11 changes: 7 additions & 4 deletions src/benchmark/scheduler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,9 @@ impl<'a> Scheduler<'a> {
self.results
.push(Benchmark::new(number, cmd, self.options, &*executor).run()?);

// We export (all results so far) after each individual benchmark, because
// we would risk losing all results if a later benchmark fails.
self.export_manager
.write_results(&self.results, self.options.time_unit)?;
// We export results after each individual benchmark, because
// we would risk losing them if a later benchmark fails.
self.export_manager.write_results(&self.results, true)?;
}

Ok(())
Expand Down Expand Up @@ -94,4 +93,8 @@ impl<'a> Scheduler<'a> {
);
}
}

pub fn final_export(&self) -> Result<()> {
self.export_manager.write_results(&self.results, false)
}
}
1 change: 1 addition & 0 deletions src/export/markup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub enum Alignment {
Left,
Right,
}

pub trait MarkupExporter {
fn table_results(&self, entries: &[BenchmarkResultWithRelativeSpeed], unit: Unit) -> String {
// prepare table header strings
Expand Down
57 changes: 40 additions & 17 deletions src/export/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,22 +45,31 @@ trait Exporter {
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>,
filename: String,
target: ExportTarget,
}

/// Handles the management of multiple file exporters.
#[derive(Default)]
pub struct ExportManager {
exporters: Vec<ExporterWithFilename>,
exporters: Vec<ExporterWithTarget>,
time_unit: Option<Unit>,
}

impl ExportManager {
/// Build the ExportManager that will export the results specified
/// in the given ArgMatches
pub fn from_cli_arguments(matches: &ArgMatches) -> Result<Self> {
let mut export_manager = Self::default();
pub fn from_cli_arguments(matches: &ArgMatches, time_unit: Option<Unit>) -> Result<Self> {
let mut export_manager = Self {
exporters: vec![],
time_unit,
};
{
let mut add_exporter = |flag, exporttype| -> Result<()> {
if let Some(filename) = matches.get_one::<String>(flag) {
Expand All @@ -87,29 +96,43 @@ impl ExportManager {
ExportType::Orgmode => Box::<OrgmodeExporter>::default(),
};

self.exporters.push(ExporterWithFilename {
self.exporters.push(ExporterWithTarget {
exporter,
filename: if filename == "-" {
if cfg!(windows) {
"con:".to_string()
} else {
"/dev/stdout".to_string()
}
target: if filename == "-" {
ExportTarget::Stdout
} else {
let _ = File::create(filename)
.with_context(|| format!("Could not create export file '{}'", filename))?;
filename.to_string()
ExportTarget::File(filename.to_string())
},
});

Ok(())
}

/// Write the given results to all Exporters contained within this manager
pub fn write_results(&self, results: &[BenchmarkResult], unit: Option<Unit>) -> Result<()> {
/// Write the given results to all Exporters. The 'intermediate' flag specifies
/// 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 {
let file_content = e.exporter.serialize(results, unit)?;
write_to_file(&e.filename, &file_content)?;
let content = || e.exporter.serialize(results, self.time_unit);

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(())
}
Expand Down
3 changes: 2 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,14 @@ fn run() -> Result<()> {
let cli_arguments = get_cli_arguments(env::args_os());
let options = Options::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)?;

let mut scheduler = Scheduler::new(&commands, &options, &export_manager);
scheduler.run_benchmarks()?;
scheduler.print_relative_speed_comparison();
scheduler.final_export()?;

Ok(())
}
Expand Down

0 comments on commit 2793d7b

Please sign in to comment.