diff --git a/lib/bencher_adapter/src/adapters/rust/criterion.rs b/lib/bencher_adapter/src/adapters/rust/criterion.rs index 9dbd245d7..ddaf8c857 100644 --- a/lib/bencher_adapter/src/adapters/rust/criterion.rs +++ b/lib/bencher_adapter/src/adapters/rust/criterion.rs @@ -1,7 +1,7 @@ use bencher_json::{project::report::JsonAverage, BenchmarkName, JsonMetric}; use nom::{ bytes::complete::tag, - character::complete::{anychar, space1}, + character::complete::{anychar, space1, space0}, combinator::{eof, map, map_res}, multi::many_till, sequence::{delimited, tuple}, @@ -48,8 +48,9 @@ fn parse_criterion<'i>( input: &'i str, ) -> IResult<&'i str, (BenchmarkName, JsonMetric)> { map_res( - many_till(anychar, parse_criterion_time), - |(name_chars, json_metric)| -> Result<(BenchmarkName, JsonMetric), NomError> { + many_till(anychar, tuple((parse_criterion_time, nom::combinator::opt(tuple((nom::character::complete::multispace1, parse_criterion_throughput)))))), + |(name_chars, (json_metric, throuput))| -> Result<(BenchmarkName, JsonMetric), NomError> { + dbg!(throuput); let name: String = if name_chars.is_empty() { prior_line.ok_or_else(|| nom_error(String::new()))?.into() } else { @@ -65,32 +66,43 @@ fn parse_criterion_time(input: &str) -> IResult<&str, JsonMetric> { map( tuple(( tuple((space1, tag("time:"), space1)), - parse_criterion_metric, + parse_criterion_metric(parse_criterion_duration), eof, )), |(_, json_metric, _)| json_metric, )(input) } -fn parse_criterion_metric(input: &str) -> IResult<&str, JsonMetric> { +fn parse_criterion_throughput(input: &str) -> IResult<&str, JsonMetric> { + dbg!(input); map( - delimited( - tag("["), - tuple(( - parse_criterion_duration, - space1, - parse_criterion_duration, - space1, - parse_criterion_duration, - )), - tag("]"), - ), - |(lower_value, _, value, _, upper_value)| JsonMetric { + tuple(( + tuple((space0, tag("thrpt:"), space1)), + parse_criterion_metric(parse_criterion_elements), + eof, + )), + |(_, metric, _)| metric, + )(input) +} + +fn parse_criterion_metric<'i, P>(mut part: P) -> impl FnMut(&'i str) -> IResult<&'i str, JsonMetric> where P: FnMut(&'i str) -> IResult<&'i str, OrderedFloat> + Copy { + move |input| { + let (input, _) = tag("[")(input)?; + + let (input, lower_value) = part(input)?; + let (input, _) = space1(input)?; + let (input, value) = part(input)?; + let (input, _) = space1(input)?; + let (input, upper_value) = part(input)?; + + let (input, _) = tag("]")(input)?; + + Ok((input, JsonMetric { value, lower_value: Some(lower_value), upper_value: Some(upper_value), - }, - )(input) + })) + } } fn parse_criterion_duration(input: &str) -> IResult<&str, OrderedFloat> { @@ -100,18 +112,32 @@ fn parse_criterion_duration(input: &str) -> IResult<&str, OrderedFloat> { )(input) } +fn parse_criterion_elements(input: &str) -> IResult<&str, OrderedFloat> { + map( + tuple(( + parse_f64, space1, nom::branch::alt(( + map(tag("Melem/s"), |_| 1000 * 1000), + map(tag("Kelem/s"), |_| 1000), + map(tag("elem/s"), |_| 1), + )), + )), + |(base, _, multiplier)| OrderedFloat(base * multiplier as f64), + )(input) +} + #[cfg(test)] #[allow(clippy::unwrap_used)] pub(crate) mod test_rust_criterion { use bencher_json::{project::report::JsonAverage, JsonMetric}; use pretty_assertions::assert_eq; + use ordered_float::OrderedFloat; use crate::{ adapters::test_util::{convert_file_path, opt_convert_file_path, validate_latency}, Adaptable, AdapterResults, Settings, }; - use super::{parse_criterion, AdapterRustCriterion}; + use super::{parse_criterion, parse_criterion_throughput, AdapterRustCriterion}; fn convert_rust_criterion(suffix: &str) -> AdapterResults { let file_path = format!("./tool_output/rust/criterion/{suffix}.txt"); @@ -258,4 +284,14 @@ pub(crate) mod test_rust_criterion { let metrics = results.get("Adapter::Rust").unwrap(); validate_latency(metrics, 14884.0, Some(14881.0), Some(14887.0)); } + + #[test] + fn parse_throughputs() { + let (_, tmp) = parse_criterion_throughput("thrpt: [3.2268 Melem/s 3.2314 Melem/s 3.2352 Melem/s]").unwrap(); + assert_eq!(JsonMetric { + value: OrderedFloat(3231400.0), + lower_value: Some(OrderedFloat(3226800.0)), + upper_value: Some(OrderedFloat(3235200.0)), + }, tmp); + } } diff --git a/lib/bencher_adapter/tool_output/rust/criterion/throughput.txt b/lib/bencher_adapter/tool_output/rust/criterion/throughput.txt new file mode 100644 index 000000000..b59e531f9 --- /dev/null +++ b/lib/bencher_adapter/tool_output/rust/criterion/throughput.txt @@ -0,0 +1,19 @@ +Benchmarking execution/naive/select_1_column/10 +Benchmarking execution/naive/select_1_column/10: Warming up for 3.0000 s +Benchmarking execution/naive/select_1_column/10: Collecting 100 samples in estimated 5.0403 s (490k iterations) +Benchmarking execution/naive/select_1_column/10: Analyzing +execution/naive/select_1_column/10 + time: [7.6998 µs 7.7152 µs 7.7294 µs] + thrpt: [1.2938 Melem/s 1.2961 Melem/s 1.2987 Melem/s] +Found 1 outliers among 100 measurements (1.00%) + 1 (1.00%) high severe +Benchmarking execution/naive/select_1_column/100 +Benchmarking execution/naive/select_1_column/100: Warming up for 3.0000 s +Benchmarking execution/naive/select_1_column/100: Collecting 100 samples in estimated 5.1599 s (141k iterations) +Benchmarking execution/naive/select_1_column/100: Analyzing +execution/naive/select_1_column/100 + time: [30.910 µs 30.946 µs 30.991 µs] + thrpt: [3.2268 Melem/s 3.2314 Melem/s 3.2352 Melem/s] +Found 2 outliers among 100 measurements (2.00%) + 1 (1.00%) high mild + 1 (1.00%) high severe