diff options
author | Serhiy Barhamon <sergey@bargamon.ru> | 2023-02-12 19:40:45 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-12 17:40:45 +0000 |
commit | fc843d035c0cb4936d9b87670e282667a9a8b265 (patch) | |
tree | c17daf4a38a78342bcf458dfad186768a72c82b1 | |
parent | 5a83af4837c016d89378f9fa982141b34ff30a23 (diff) |
feat(bench): Add JSON reporter for "deno bench" subcommand (#17595)
-rw-r--r-- | cli/args/flags.rs | 13 | ||||
-rw-r--r-- | cli/args/mod.rs | 2 | ||||
-rw-r--r-- | cli/tools/bench.rs | 90 |
3 files changed, 101 insertions, 4 deletions
diff --git a/cli/args/flags.rs b/cli/args/flags.rs index 792ed8775..ee8ec2563 100644 --- a/cli/args/flags.rs +++ b/cli/args/flags.rs @@ -54,6 +54,7 @@ pub struct FileFlags { pub struct BenchFlags { pub files: FileFlags, pub filter: Option<String>, + pub json: bool, } #[derive(Clone, Debug, Eq, PartialEq)] @@ -718,6 +719,12 @@ fn bench_subcommand<'a>() -> Command<'a> { runtime_args(Command::new("bench"), true, false) .trailing_var_arg(true) .arg( + Arg::new("json") + .long("json") + .help("UNSTABLE: Output benchmark result in JSON format") + .takes_value(false), + ) + .arg( Arg::new("ignore") .long("ignore") .takes_value(true) @@ -2325,6 +2332,8 @@ fn bench_parse(flags: &mut Flags, matches: &clap::ArgMatches) { // interactive prompts, unless done by user code flags.no_prompt = true; + let json = matches.is_present("json"); + let ignore = match matches.values_of("ignore") { Some(f) => f.map(PathBuf::from).collect(), None => vec![], @@ -2359,6 +2368,7 @@ fn bench_parse(flags: &mut Flags, matches: &clap::ArgMatches) { flags.subcommand = DenoSubcommand::Bench(BenchFlags { files: FileFlags { include, ignore }, filter, + json, }); } @@ -6535,6 +6545,7 @@ mod tests { let r = flags_from_vec(svec![ "deno", "bench", + "--json", "--unstable", "--filter", "- foo", @@ -6552,6 +6563,7 @@ mod tests { Flags { subcommand: DenoSubcommand::Bench(BenchFlags { filter: Some("- foo".to_string()), + json: true, files: FileFlags { include: vec![PathBuf::from("dir1/"), PathBuf::from("dir2/")], ignore: vec![], @@ -6576,6 +6588,7 @@ mod tests { Flags { subcommand: DenoSubcommand::Bench(BenchFlags { filter: None, + json: false, files: FileFlags { include: vec![], ignore: vec![], diff --git a/cli/args/mod.rs b/cli/args/mod.rs index 95dfa4535..da36c7071 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -105,6 +105,7 @@ impl CacheSetting { pub struct BenchOptions { pub files: FilesConfig, pub filter: Option<String>, + pub json: bool, } impl BenchOptions { @@ -119,6 +120,7 @@ impl BenchOptions { Some(bench_flags.files), ), filter: bench_flags.filter, + json: bench_flags.json, }) } } diff --git a/cli/tools/bench.rs b/cli/tools/bench.rs index be0d9ba6c..447cb1fcb 100644 --- a/cli/tools/bench.rs +++ b/cli/tools/bench.rs @@ -4,6 +4,7 @@ use crate::args::BenchOptions; use crate::args::CliOptions; use crate::args::TypeCheckMode; use crate::colors; +use crate::display::write_json_to_stdout; use crate::graph_util::graph_valid_with_cli_options; use crate::ops; use crate::proc_state::ProcState; @@ -13,6 +14,7 @@ use crate::util::file_watcher; use crate::util::file_watcher::ResolutionResult; use crate::util::fs::collect_specifiers; use crate::util::path::is_supported_ext; +use crate::version::get_user_agent; use crate::worker::create_main_worker_for_test_or_bench; use deno_core::error::generic_error; @@ -41,6 +43,7 @@ use tokio::sync::mpsc::UnboundedSender; #[derive(Debug, Clone)] struct BenchSpecifierOptions { filter: TestFilter, + json: bool, } #[derive(Debug, Clone, Eq, PartialEq, Deserialize)] @@ -62,7 +65,7 @@ pub enum BenchEvent { Result(usize, BenchResult), } -#[derive(Debug, Clone, Deserialize)] +#[derive(Debug, Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub enum BenchResult { Ok(BenchStats), @@ -109,7 +112,13 @@ impl BenchReport { } } -fn create_reporter(show_output: bool) -> Box<dyn BenchReporter + Send> { +fn create_reporter( + show_output: bool, + json: bool, +) -> Box<dyn BenchReporter + Send> { + if json { + return Box::new(JsonReporter::new()); + } Box::new(ConsoleReporter::new(show_output)) } @@ -123,6 +132,74 @@ pub trait BenchReporter { fn report_result(&mut self, desc: &BenchDescription, result: &BenchResult); } +#[derive(Debug, Serialize)] +struct JsonReporterResult { + runtime: String, + cpu: String, + origin: String, + group: Option<String>, + name: String, + baseline: bool, + result: BenchResult, +} + +impl JsonReporterResult { + fn new( + origin: String, + group: Option<String>, + name: String, + baseline: bool, + result: BenchResult, + ) -> Self { + Self { + runtime: format!("{} {}", get_user_agent(), env!("TARGET")), + cpu: mitata::cpu::name(), + origin, + group, + name, + baseline, + result, + } + } +} + +#[derive(Debug, Serialize)] +struct JsonReporter(Vec<JsonReporterResult>); +impl JsonReporter { + fn new() -> Self { + Self(vec![]) + } +} + +impl BenchReporter for JsonReporter { + fn report_group_summary(&mut self) {} + #[cold] + fn report_plan(&mut self, _plan: &BenchPlan) {} + + fn report_end(&mut self, _report: &BenchReport) { + match write_json_to_stdout(self) { + Ok(_) => (), + Err(e) => println!("{e}"), + } + } + + fn report_register(&mut self, _desc: &BenchDescription) {} + + fn report_wait(&mut self, _desc: &BenchDescription) {} + + fn report_output(&mut self, _output: &str) {} + + fn report_result(&mut self, desc: &BenchDescription, result: &BenchResult) { + self.0.push(JsonReporterResult::new( + desc.origin.clone(), + desc.group.clone(), + desc.name.clone(), + desc.baseline, + result.clone(), + )); + } +} + struct ConsoleReporter { name: String, show_output: bool, @@ -376,12 +453,14 @@ async fn bench_specifiers( let (sender, mut receiver) = unbounded_channel::<BenchEvent>(); + let option_for_handles = options.clone(); + let join_handles = specifiers.into_iter().map(move |specifier| { let ps = ps.clone(); let permissions = permissions.clone(); let specifier = specifier; let sender = sender.clone(); - let options = options.clone(); + let options = option_for_handles.clone(); tokio::task::spawn_blocking(move || { let future = bench_specifier(ps, permissions, specifier, sender, options); @@ -398,7 +477,8 @@ async fn bench_specifiers( tokio::task::spawn(async move { let mut used_only = false; let mut report = BenchReport::new(); - let mut reporter = create_reporter(log_level != Some(Level::Error)); + let mut reporter = + create_reporter(log_level != Some(Level::Error), options.json); let mut benches = IndexMap::new(); while let Some(event) = receiver.recv().await { @@ -509,6 +589,7 @@ pub async fn run_benchmarks( specifiers, BenchSpecifierOptions { filter: TestFilter::from_flag(&bench_options.filter), + json: bench_options.json, }, ) .await?; @@ -658,6 +739,7 @@ pub async fn run_benchmarks_with_watch( specifiers, BenchSpecifierOptions { filter: TestFilter::from_flag(&bench_options.filter), + json: bench_options.json, }, ) .await?; |