mirror of
https://github.com/sharkdp/hyperfine.git
synced 2024-09-11 14:07:02 +03:00
Merge 539995aad1
into 4a00f1821c
This commit is contained in:
commit
83267e44e1
@ -1,20 +1,20 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use serde::Serialize;
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::util::units::Second;
|
use crate::util::units::Second;
|
||||||
|
|
||||||
/// Set of values that will be exported.
|
/// Set of values that will be exported.
|
||||||
// NOTE: `serde` is used for JSON serialization, but not for CSV serialization due to the
|
// NOTE: `serde` is used for JSON serialization, but not for CSV serialization due to the
|
||||||
// `parameters` map. Update `src/hyperfine/export/csv.rs` with new fields, as appropriate.
|
// `parameters` map. Update `src/hyperfine/export/csv.rs` with new fields, as appropriate.
|
||||||
#[derive(Debug, Default, Clone, Serialize, PartialEq)]
|
#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq)]
|
||||||
pub struct BenchmarkResult {
|
pub struct BenchmarkResult {
|
||||||
/// The full command line of the program that is being benchmarked
|
/// The full command line of the program that is being benchmarked
|
||||||
pub command: String,
|
pub command: String,
|
||||||
|
|
||||||
/// The full command line of the program that is being benchmarked, possibly including a list of
|
/// The full command line of the program that is being benchmarked, possibly including a list of
|
||||||
/// parameters that were not used in the command line template.
|
/// parameters that were not used in the command line template.
|
||||||
#[serde(skip_serializing)]
|
#[serde(skip)]
|
||||||
pub command_with_unused_parameters: String,
|
pub command_with_unused_parameters: String,
|
||||||
|
|
||||||
/// The average run time
|
/// The average run time
|
||||||
@ -46,6 +46,6 @@ pub struct BenchmarkResult {
|
|||||||
pub exit_codes: Vec<Option<i32>>,
|
pub exit_codes: Vec<Option<i32>>,
|
||||||
|
|
||||||
/// Parameter values for this benchmark
|
/// Parameter values for this benchmark
|
||||||
#[serde(skip_serializing_if = "BTreeMap::is_empty")]
|
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
|
||||||
pub parameters: BTreeMap<String, String>,
|
pub parameters: BTreeMap<String, String>,
|
||||||
}
|
}
|
||||||
|
@ -22,12 +22,13 @@ impl<'a> Scheduler<'a> {
|
|||||||
commands: &'a Commands,
|
commands: &'a Commands,
|
||||||
options: &'a Options,
|
options: &'a Options,
|
||||||
export_manager: &'a ExportManager,
|
export_manager: &'a ExportManager,
|
||||||
|
results: &'a Vec<BenchmarkResult>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
commands,
|
commands,
|
||||||
options,
|
options,
|
||||||
export_manager,
|
export_manager,
|
||||||
results: vec![],
|
results: results.to_vec(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,6 +70,14 @@ impl<'a> Scheduler<'a> {
|
|||||||
&self.results,
|
&self.results,
|
||||||
self.options.sort_order_speed_comparison,
|
self.options.sort_order_speed_comparison,
|
||||||
) {
|
) {
|
||||||
|
fn get_command_from_result<'b>(result: &'b BenchmarkResult) -> &'b str {
|
||||||
|
if !result.command_with_unused_parameters.is_empty() {
|
||||||
|
&result.command_with_unused_parameters
|
||||||
|
} else {
|
||||||
|
&result.command
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match self.options.sort_order_speed_comparison {
|
match self.options.sort_order_speed_comparison {
|
||||||
SortOrder::MeanTime => {
|
SortOrder::MeanTime => {
|
||||||
println!("{}", "Summary".bold());
|
println!("{}", "Summary".bold());
|
||||||
@ -78,7 +87,7 @@ impl<'a> Scheduler<'a> {
|
|||||||
|
|
||||||
println!(
|
println!(
|
||||||
" {} ran",
|
" {} ran",
|
||||||
fastest.result.command_with_unused_parameters.cyan()
|
(get_command_from_result(&fastest.result)).cyan()
|
||||||
);
|
);
|
||||||
|
|
||||||
for item in others {
|
for item in others {
|
||||||
@ -90,7 +99,8 @@ impl<'a> Scheduler<'a> {
|
|||||||
} else {
|
} else {
|
||||||
"".into()
|
"".into()
|
||||||
},
|
},
|
||||||
&item.result.command_with_unused_parameters.magenta()
|
// &item.result.command_with_unused_parameters.magenta()
|
||||||
|
&(get_command_from_result(&item.result)).magenta()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,7 +118,7 @@ impl<'a> Scheduler<'a> {
|
|||||||
} else {
|
} else {
|
||||||
" ".into()
|
" ".into()
|
||||||
},
|
},
|
||||||
&item.result.command_with_unused_parameters,
|
&(get_command_from_result(item.result)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -283,6 +283,13 @@ fn build_command() -> Command {
|
|||||||
.help("Export the timing summary statistics and timings of individual runs as JSON to the given FILE. \
|
.help("Export the timing summary statistics and timings of individual runs as JSON to the given FILE. \
|
||||||
The output time unit is always seconds"),
|
The output time unit is always seconds"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("import-json")
|
||||||
|
.long("import-json")
|
||||||
|
.action(ArgAction::Set)
|
||||||
|
.value_name("FILE")
|
||||||
|
.help("Import the timing summary statistics and timings of individual runs from a JSON FILE.")
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("export-markdown")
|
Arg::new("export-markdown")
|
||||||
.long("export-markdown")
|
.long("export-markdown")
|
||||||
|
@ -8,9 +8,9 @@ use crate::util::units::Unit;
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
#[derive(Serialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
struct HyperfineSummary<'a> {
|
pub struct HyperfineSummary {
|
||||||
results: &'a [BenchmarkResult],
|
pub results: Vec<BenchmarkResult>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
@ -23,7 +23,9 @@ impl Exporter for JsonExporter {
|
|||||||
_unit: Option<Unit>,
|
_unit: Option<Unit>,
|
||||||
_sort_order: SortOrder,
|
_sort_order: SortOrder,
|
||||||
) -> Result<Vec<u8>> {
|
) -> Result<Vec<u8>> {
|
||||||
let mut output = to_vec_pretty(&HyperfineSummary { results });
|
let mut output = to_vec_pretty(&HyperfineSummary {
|
||||||
|
results: results.to_vec(),
|
||||||
|
});
|
||||||
if let Ok(ref mut content) = output {
|
if let Ok(ref mut content) = output {
|
||||||
content.push(b'\n');
|
content.push(b'\n');
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ use std::io::Write;
|
|||||||
|
|
||||||
mod asciidoc;
|
mod asciidoc;
|
||||||
mod csv;
|
mod csv;
|
||||||
mod json;
|
pub mod json;
|
||||||
mod markdown;
|
mod markdown;
|
||||||
mod markup;
|
mod markup;
|
||||||
mod orgmode;
|
mod orgmode;
|
||||||
|
31
src/import.rs
Normal file
31
src/import.rs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
use crate::{benchmark::benchmark_result::BenchmarkResult, export::json::HyperfineSummary};
|
||||||
|
use clap::ArgMatches;
|
||||||
|
use std::fs;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct Importer {}
|
||||||
|
|
||||||
|
impl Importer {
|
||||||
|
pub fn from_cli_arguments(matches: &ArgMatches) -> Option<Vec<BenchmarkResult>> {
|
||||||
|
match matches.get_one::<String>("import-json") {
|
||||||
|
Some(file_name) => read_summary_from_file(file_name),
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_summary_from_file(file_name: &str) -> Option<Vec<BenchmarkResult>> {
|
||||||
|
let file_content = match fs::read_to_string(file_name) {
|
||||||
|
Ok(content) => content,
|
||||||
|
Err(_) => {
|
||||||
|
eprintln!("Unable to load previous run from file {}", file_name);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let hyperfine_summary = serde_json::from_str::<HyperfineSummary>(&file_content);
|
||||||
|
match hyperfine_summary {
|
||||||
|
Ok(summary) => Some(summary.results),
|
||||||
|
Err(_) => None,
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,7 @@ use benchmark::scheduler::Scheduler;
|
|||||||
use cli::get_cli_arguments;
|
use cli::get_cli_arguments;
|
||||||
use command::Commands;
|
use command::Commands;
|
||||||
use export::ExportManager;
|
use export::ExportManager;
|
||||||
|
use import::Importer;
|
||||||
use options::Options;
|
use options::Options;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
@ -19,6 +20,7 @@ pub mod cli;
|
|||||||
pub mod command;
|
pub mod command;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod export;
|
pub mod export;
|
||||||
|
pub mod import;
|
||||||
pub mod options;
|
pub mod options;
|
||||||
pub mod outlier_detection;
|
pub mod outlier_detection;
|
||||||
pub mod output;
|
pub mod output;
|
||||||
@ -32,13 +34,15 @@ fn run() -> Result<()> {
|
|||||||
colored::control::set_virtual_terminal(true).unwrap();
|
colored::control::set_virtual_terminal(true).unwrap();
|
||||||
|
|
||||||
let cli_arguments = get_cli_arguments(env::args_os());
|
let cli_arguments = get_cli_arguments(env::args_os());
|
||||||
|
let previous_results = Importer::from_cli_arguments(&cli_arguments).unwrap_or(Vec::new());
|
||||||
|
|
||||||
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, options.time_unit)?;
|
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, &previous_results);
|
||||||
scheduler.run_benchmarks()?;
|
scheduler.run_benchmarks()?;
|
||||||
scheduler.print_relative_speed_comparison();
|
scheduler.print_relative_speed_comparison();
|
||||||
scheduler.final_export()?;
|
scheduler.final_export()?;
|
||||||
|
Loading…
Reference in New Issue
Block a user