mirror of
https://github.com/denoland/deno.git
synced 2024-12-22 07:14:47 -05:00
feat(bench): Add JSON reporter for "deno bench" subcommand (#17595)
This commit is contained in:
parent
5a83af4837
commit
fc843d035c
3 changed files with 101 additions and 4 deletions
|
@ -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)]
|
||||
|
@ -717,6 +718,12 @@ fn clap_root(version: &str) -> Command {
|
|||
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")
|
||||
|
@ -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![],
|
||||
|
|
|
@ -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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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?;
|
||||
|
|
Loading…
Reference in a new issue