diff --git a/lib/bencher_adapter/src/adapters/rust/gungraun/gungraun_json.rs b/lib/bencher_adapter/src/adapters/rust/gungraun/gungraun_json.rs new file mode 100644 index 000000000..ad5f38949 --- /dev/null +++ b/lib/bencher_adapter/src/adapters/rust/gungraun/gungraun_json.rs @@ -0,0 +1,525 @@ +use std::{collections::HashMap, hash::Hash}; + +use bencher_json::{project::report::JsonAverage, BenchmarkName, JsonNewMetric}; +use serde::Deserialize; + +use crate::{ + results::adapter_results::{AdapterResults, GungraunMeasure}, + Adaptable, Settings, +}; + +pub struct AdapterRustGungraunJson; + +impl Adaptable for AdapterRustGungraunJson { + fn parse(input: &str, settings: Settings) -> Option { + match settings.average { + None => {}, + Some(JsonAverage::Mean | JsonAverage::Median) => { + return None; // 'gungraun' results are for a single run only. + }, + } + + let results: Vec = match serde_json::from_str(input) { + Ok(results) => results, + Err(_) => { + debug_assert!(false, "Error deserializing input as gungraun JSON."); + return None; + }, + }; + + AdapterResults::new_gungraun( + results + .into_iter() + .flat_map(Into::)>>::into) + .collect(), + ) + } +} + +#[derive(Deserialize)] +struct BenchmarkResult { + id: String, + module_path: String, + profiles: Vec, +} + +impl From for Option<(BenchmarkName, Vec)> { + fn from(value: BenchmarkResult) -> Self { + Some(( + format!("{}::{}", value.module_path, value.id) + .parse() + .ok()?, + value + .profiles + .into_iter() + .flat_map(Into::>::into) + .collect(), + )) + } +} + +#[derive(Deserialize)] +struct Profile { + summaries: ProfileData, + tool: ValgrindTool, +} + +impl From for Vec { + fn from(value: Profile) -> Self { + match value.summaries.total.summary { + ToolMetricSummary::None => Vec::new(), + ToolMetricSummary::ErrorTool(metrics) => { + Vec::<(ErrorMetric, JsonNewMetric)>::from(metrics) + .into_iter() + .map(|(key, json_metric)| match value.tool { + ValgrindTool::DRD => match key { + ErrorMetric::Errors => GungraunMeasure::DrdErrors(json_metric), + ErrorMetric::Contexts => GungraunMeasure::DrdContexts(json_metric), + ErrorMetric::SuppressedErrors => { + GungraunMeasure::DrdSuppressedErrors(json_metric) + }, + ErrorMetric::SuppressedContexts => { + GungraunMeasure::DrdSuppressedContexts(json_metric) + }, + }, + ValgrindTool::Helgrind => match key { + ErrorMetric::Errors => GungraunMeasure::HelgrindErrors(json_metric), + ErrorMetric::Contexts => GungraunMeasure::HelgrindContexts(json_metric), + ErrorMetric::SuppressedErrors => { + GungraunMeasure::HelgrindSuppressedErrors(json_metric) + }, + ErrorMetric::SuppressedContexts => { + GungraunMeasure::HelgrindSuppressedContexts(json_metric) + }, + }, + ValgrindTool::Memcheck => match key { + ErrorMetric::Errors => GungraunMeasure::MemcheckErrors(json_metric), + ErrorMetric::Contexts => GungraunMeasure::MemcheckContexts(json_metric), + ErrorMetric::SuppressedErrors => { + GungraunMeasure::MemcheckSuppressedErrors(json_metric) + }, + ErrorMetric::SuppressedContexts => { + GungraunMeasure::MemcheckSuppressedContexts(json_metric) + }, + }, + _ => GungraunMeasure::Unknown, + }) + .collect() + }, + ToolMetricSummary::Dhat(metrics) => metrics.into(), + ToolMetricSummary::Callgrind(metrics) => metrics.into(), + ToolMetricSummary::Cachegrind(metrics) => metrics.into(), + } + } +} + +#[derive(Deserialize)] +struct ProfileData { + total: ProfileTotal, +} + +#[derive(Deserialize)] +struct ProfileTotal { + summary: ToolMetricSummary, +} + +#[derive(Deserialize)] +enum ToolMetricSummary { + None, + ErrorTool(MetricsSummary), + Dhat(MetricsSummary), + Callgrind(MetricsSummary), + Cachegrind(MetricsSummary), +} + +#[derive(Deserialize)] +pub enum ValgrindTool { + /// [Callgrind: a call-graph generating cache and branch prediction profiler](https://valgrind.org/docs/manual/cl-manual.html) + Callgrind, + /// [Cachegrind: a high-precision tracing profiler](https://valgrind.org/docs/manual/cg-manual.html) + Cachegrind, + /// [DHAT: a dynamic heap analysis tool](https://valgrind.org/docs/manual/dh-manual.html) + DHAT, + /// [Memcheck: a memory error detector](https://valgrind.org/docs/manual/mc-manual.html) + Memcheck, + /// [Helgrind: a thread error detector](https://valgrind.org/docs/manual/hg-manual.html) + Helgrind, + /// [DRD: a thread error detector](https://valgrind.org/docs/manual/drd-manual.html) + DRD, + /// [Massif: a heap profiler](https://valgrind.org/docs/manual/ms-manual.html) + Massif, + /// [BBV: an experimental basic block vector generation tool](https://valgrind.org/docs/manual/bbv-manual.html) + BBV, +} + +#[derive(Deserialize)] +struct MetricsSummary(HashMap); + +impl From> for Vec<(ErrorMetric, JsonNewMetric)> { + fn from(value: MetricsSummary) -> Self { + value + .0 + .into_iter() + .map(|(key, value)| { + let json_metric: JsonNewMetric = value.into(); + (key, json_metric) + }) + .collect() + } +} + +impl From> for Vec { + fn from(value: MetricsSummary) -> Self { + value + .0 + .into_iter() + .map(|(key, value)| { + let json_metric: JsonNewMetric = value.into(); + match key { + DhatMetric::TotalUnits => GungraunMeasure::TotalUnits(json_metric), + DhatMetric::TotalEvents => GungraunMeasure::TotalEvents(json_metric), + DhatMetric::TotalBytes => GungraunMeasure::TotalBytes(json_metric), + DhatMetric::TotalBlocks => GungraunMeasure::TotalBlocks(json_metric), + DhatMetric::AtTGmaxBytes => GungraunMeasure::AtTGmaxBytes(json_metric), + DhatMetric::AtTGmaxBlocks => GungraunMeasure::AtTGmaxBlocks(json_metric), + DhatMetric::AtTEndBytes => GungraunMeasure::AtTEndBytes(json_metric), + DhatMetric::AtTEndBlocks => GungraunMeasure::AtTEndBlocks(json_metric), + DhatMetric::ReadsBytes => GungraunMeasure::ReadsBytes(json_metric), + DhatMetric::WritesBytes => GungraunMeasure::WritesBytes(json_metric), + DhatMetric::TotalLifetimes => GungraunMeasure::TotalLifetimes(json_metric), + DhatMetric::MaximumBytes => GungraunMeasure::MaximumBytes(json_metric), + DhatMetric::MaximumBlocks => GungraunMeasure::MaximumBlocks(json_metric), + } + }) + .collect() + } +} + +impl From> for Vec { + fn from(value: MetricsSummary) -> Self { + value + .0 + .into_iter() + .map(|(key, value)| { + let json_metric: JsonNewMetric = value.into(); + match key { + EventKind::Ir => GungraunMeasure::Instructions(json_metric), + EventKind::Dr => GungraunMeasure::DataCacheReads(json_metric), + EventKind::Dw => GungraunMeasure::DataCacheWrites(json_metric), + EventKind::I1mr => GungraunMeasure::L1InstrCacheReadMisses(json_metric), + EventKind::D1mr => GungraunMeasure::L1DataCacheReadMisses(json_metric), + EventKind::D1mw => GungraunMeasure::L1DataCacheWriteMisses(json_metric), + EventKind::ILmr => GungraunMeasure::LLInstrCacheReadMisses(json_metric), + EventKind::DLmr => GungraunMeasure::LLDataCacheReadMisses(json_metric), + EventKind::DLmw => GungraunMeasure::LLDataCacheWriteMisses(json_metric), + EventKind::I1MissRate => GungraunMeasure::L1InstrCacheMissRate(json_metric), + EventKind::LLiMissRate => GungraunMeasure::LLInstrCacheMissRate(json_metric), + EventKind::D1MissRate => GungraunMeasure::L1DataCacheMissRate(json_metric), + EventKind::LLdMissRate => GungraunMeasure::LLDataCacheMissRate(json_metric), + EventKind::LLMissRate => GungraunMeasure::LLCacheMissRate(json_metric), + EventKind::L1hits => GungraunMeasure::L1Hits(json_metric), + EventKind::LLhits => GungraunMeasure::LLHits(json_metric), + EventKind::RamHits => GungraunMeasure::RamHits(json_metric), + EventKind::L1HitRate => GungraunMeasure::L1HitRate(json_metric), + EventKind::LLHitRate => GungraunMeasure::LLHitRate(json_metric), + EventKind::RamHitRate => GungraunMeasure::RamHitRate(json_metric), + EventKind::TotalRW => GungraunMeasure::TotalReadWrite(json_metric), + EventKind::EstimatedCycles => GungraunMeasure::EstimatedCycles(json_metric), + EventKind::SysCount => GungraunMeasure::NumberSystemCalls(json_metric), + EventKind::SysTime => GungraunMeasure::TimeSystemCalls(json_metric), + EventKind::SysCpuTime => GungraunMeasure::CpuTimeSystemCalls(json_metric), + EventKind::Ge => GungraunMeasure::GlobalBusEvents(json_metric), + EventKind::Bc => GungraunMeasure::ExecutedConditionalBranches(json_metric), + EventKind::Bcm => GungraunMeasure::MispredictedConditionalBranches(json_metric), + EventKind::Bi => GungraunMeasure::ExecutedIndirectBranches(json_metric), + EventKind::Bim => GungraunMeasure::MispredictedIndirectBranches(json_metric), + EventKind::ILdmr => GungraunMeasure::DirtyMissInstructionRead(json_metric), + EventKind::DLdmr => GungraunMeasure::DirtyMissDataRead(json_metric), + EventKind::DLdmw => GungraunMeasure::DirtyMissDataWrite(json_metric), + EventKind::AcCost1 => GungraunMeasure::L1BadTemporalLocality(json_metric), + EventKind::AcCost2 => GungraunMeasure::LLBadTemporalLocality(json_metric), + EventKind::SpLoss1 => GungraunMeasure::L1BadSpatialLocality(json_metric), + EventKind::SpLoss2 => GungraunMeasure::LLBadSpatialLocality(json_metric), + } + }) + .collect() + } +} + +impl From> for Vec { + fn from(value: MetricsSummary) -> Self { + value + .0 + .into_iter() + .map(|(key, value)| { + let json_metric: JsonNewMetric = value.into(); + match key { + CachegrindMetric::Ir => GungraunMeasure::Instructions(json_metric), + CachegrindMetric::Dr => GungraunMeasure::DataCacheReads(json_metric), + CachegrindMetric::Dw => GungraunMeasure::DataCacheWrites(json_metric), + CachegrindMetric::I1mr => GungraunMeasure::L1InstrCacheReadMisses(json_metric), + CachegrindMetric::D1mr => GungraunMeasure::L1DataCacheReadMisses(json_metric), + CachegrindMetric::D1mw => GungraunMeasure::L1DataCacheWriteMisses(json_metric), + CachegrindMetric::ILmr => GungraunMeasure::LLInstrCacheReadMisses(json_metric), + CachegrindMetric::DLmr => GungraunMeasure::LLDataCacheReadMisses(json_metric), + CachegrindMetric::DLmw => GungraunMeasure::LLDataCacheWriteMisses(json_metric), + CachegrindMetric::I1MissRate => { + GungraunMeasure::L1InstrCacheMissRate(json_metric) + }, + CachegrindMetric::LLiMissRate => { + GungraunMeasure::LLInstrCacheMissRate(json_metric) + }, + CachegrindMetric::D1MissRate => { + GungraunMeasure::L1DataCacheMissRate(json_metric) + }, + CachegrindMetric::LLdMissRate => { + GungraunMeasure::LLDataCacheMissRate(json_metric) + }, + CachegrindMetric::LLMissRate => GungraunMeasure::LLCacheMissRate(json_metric), + CachegrindMetric::L1hits => GungraunMeasure::L1Hits(json_metric), + CachegrindMetric::LLhits => GungraunMeasure::LLHits(json_metric), + CachegrindMetric::RamHits => GungraunMeasure::RamHits(json_metric), + CachegrindMetric::L1HitRate => GungraunMeasure::L1HitRate(json_metric), + CachegrindMetric::LLHitRate => GungraunMeasure::LLHitRate(json_metric), + CachegrindMetric::RamHitRate => GungraunMeasure::RamHitRate(json_metric), + CachegrindMetric::TotalRW => GungraunMeasure::TotalReadWrite(json_metric), + CachegrindMetric::EstimatedCycles => { + GungraunMeasure::EstimatedCycles(json_metric) + }, + CachegrindMetric::Bc => { + GungraunMeasure::ExecutedConditionalBranches(json_metric) + }, + CachegrindMetric::Bcm => { + GungraunMeasure::MispredictedConditionalBranches(json_metric) + }, + CachegrindMetric::Bi => GungraunMeasure::ExecutedIndirectBranches(json_metric), + CachegrindMetric::Bim => { + GungraunMeasure::MispredictedIndirectBranches(json_metric) + }, + } + }) + .collect() + } +} + +#[derive(Deserialize)] +struct MetricsDiff { + metrics: EitherOrBoth, +} + +impl From for JsonNewMetric { + fn from(value: MetricsDiff) -> Self { + let value = match value.metrics { + EitherOrBoth::Both(left, _) => left, + EitherOrBoth::Left(left) => left, + }; + + match value { + Metric::Int(v) => JsonNewMetric { + value: (v as f64).into(), + ..Default::default() + }, + Metric::Float(v) => JsonNewMetric { + value: v.into(), + ..Default::default() + }, + } + } +} + +#[derive(Deserialize)] +enum EitherOrBoth { + Both(Metric, Metric), + Left(Metric), +} + +#[derive(Deserialize)] +enum Metric { + Int(u64), + Float(f64), +} + +#[derive(Deserialize, Hash, Eq, PartialEq)] +pub enum CachegrindMetric { + /// The default event. I cache reads (which equals the number of instructions executed) + Ir, + /// D Cache reads (which equals the number of memory reads) (--cache-sim=yes) + Dr, + /// D Cache writes (which equals the number of memory writes) (--cache-sim=yes) + Dw, + /// I1 cache read misses (--cache-sim=yes) + I1mr, + /// D1 cache read misses (--cache-sim=yes) + D1mr, + /// D1 cache write misses (--cache-sim=yes) + D1mw, + /// LL cache instruction read misses (--cache-sim=yes) + ILmr, + /// LL cache data read misses (--cache-sim=yes) + DLmr, + /// LL cache data write misses (--cache-sim=yes) + DLmw, + /// I1 cache miss rate (--cache-sim=yes) + I1MissRate, + /// LL/L2 instructions cache miss rate (--cache-sim=yes) + LLiMissRate, + /// D1 cache miss rate (--cache-sim=yes) + D1MissRate, + /// LL/L2 data cache miss rate (--cache-sim=yes) + LLdMissRate, + /// LL/L2 cache miss rate (--cache-sim=yes) + LLMissRate, + /// Derived event showing the L1 hits (--cache-sim=yes) + L1hits, + /// Derived event showing the LL hits (--cache-sim=yes) + LLhits, + /// Derived event showing the RAM hits (--cache-sim=yes) + RamHits, + /// L1 cache hit rate (--cache-sim=yes) + L1HitRate, + /// LL/L2 cache hit rate (--cache-sim=yes) + LLHitRate, + /// RAM hit rate (--cache-sim=yes) + RamHitRate, + /// Derived event showing the total amount of cache reads and writes (--cache-sim=yes) + TotalRW, + /// Derived event showing estimated CPU cycles (--cache-sim=yes) + EstimatedCycles, + /// Conditional branches executed (--branch-sim=yes) + Bc, + /// Conditional branches mispredicted (--branch-sim=yes) + Bcm, + /// Indirect branches executed (--branch-sim=yes) + Bi, + /// Indirect branches mispredicted (--branch-sim=yes) + Bim, +} + +#[derive(Deserialize, Hash, Eq, PartialEq)] +pub enum EventKind { + /// The default event. I cache reads (which equals the number of instructions executed) + Ir, + /// D Cache reads (which equals the number of memory reads) (--cache-sim=yes) + Dr, + /// D Cache writes (which equals the number of memory writes) (--cache-sim=yes) + Dw, + /// I1 cache read misses (--cache-sim=yes) + I1mr, + /// D1 cache read misses (--cache-sim=yes) + D1mr, + /// D1 cache write misses (--cache-sim=yes) + D1mw, + /// LL cache instruction read misses (--cache-sim=yes) + ILmr, + /// LL cache data read misses (--cache-sim=yes) + DLmr, + /// LL cache data write misses (--cache-sim=yes) + DLmw, + /// I1 cache miss rate (--cache-sim=yes) + I1MissRate, + /// LL/L2 instructions cache miss rate (--cache-sim=yes) + LLiMissRate, + /// D1 cache miss rate (--cache-sim=yes) + D1MissRate, + /// LL/L2 data cache miss rate (--cache-sim=yes) + LLdMissRate, + /// LL/L2 cache miss rate (--cache-sim=yes) + LLMissRate, + /// Derived event showing the L1 hits (--cache-sim=yes) + L1hits, + /// Derived event showing the LL hits (--cache-sim=yes) + LLhits, + /// Derived event showing the RAM hits (--cache-sim=yes) + RamHits, + /// L1 cache hit rate (--cache-sim=yes) + L1HitRate, + /// LL/L2 cache hit rate (--cache-sim=yes) + LLHitRate, + /// RAM hit rate (--cache-sim=yes) + RamHitRate, + /// Derived event showing the total amount of cache reads and writes (--cache-sim=yes) + TotalRW, + /// Derived event showing estimated CPU cycles (--cache-sim=yes) + EstimatedCycles, + /// The number of system calls done (--collect-systime=yes) + SysCount, + /// The elapsed time spent in system calls (--collect-systime=yes) + SysTime, + /// The cpu time spent during system calls (--collect-systime=nsec) + SysCpuTime, + /// The number of global bus events (--collect-bus=yes) + Ge, + /// Conditional branches executed (--branch-sim=yes) + Bc, + /// Conditional branches mispredicted (--branch-sim=yes) + Bcm, + /// Indirect branches executed (--branch-sim=yes) + Bi, + /// Indirect branches mispredicted (--branch-sim=yes) + Bim, + /// Dirty miss because of instruction read (--simulate-wb=yes) + ILdmr, + /// Dirty miss because of data read (--simulate-wb=yes) + DLdmr, + /// Dirty miss because of data write (--simulate-wb=yes) + DLdmw, + /// Counter showing bad temporal locality for L1 caches (--cachuse=yes) + AcCost1, + /// Counter showing bad temporal locality for LL caches (--cachuse=yes) + AcCost2, + /// Counter showing bad spatial locality for L1 caches (--cachuse=yes) + SpLoss1, + /// Counter showing bad spatial locality for LL caches (--cachuse=yes) + SpLoss2, +} + +#[derive(Deserialize, Hash, Eq, PartialEq)] +pub enum DhatMetric { + /// In ad-hoc mode, Total units measured over the entire execution + TotalUnits, + /// Total ad-hoc events over the entire execution + TotalEvents, + /// Total bytes allocated over the entire execution + TotalBytes, + /// Total heap blocks allocated over the entire execution + TotalBlocks, + /// The bytes alive at t-gmax, the time when the heap size reached its global maximum + AtTGmaxBytes, + /// The blocks alive at t-gmax + AtTGmaxBlocks, + /// The amount of bytes at the end of the execution. + /// + /// This is the amount of bytes which were not explicitly freed. + AtTEndBytes, + /// The amount of blocks at the end of the execution. + /// + /// This is the amount of heap blocks which were not explicitly freed. + AtTEndBlocks, + /// The amount of bytes read during the entire execution + ReadsBytes, + /// The amount of bytes written during the entire execution + WritesBytes, + /// The total lifetimes of all heap blocks allocated + TotalLifetimes, + /// The maximum amount of bytes + MaximumBytes, + /// The maximum amount of heap blocks + MaximumBlocks, +} + +#[derive(Deserialize, Hash, Eq, PartialEq)] +pub enum ErrorMetric { + /// The amount of detected unsuppressed errors + Errors, + /// The amount of detected unsuppressed error contexts + Contexts, + /// The amount of suppressed errors + SuppressedErrors, + /// The amount of suppressed error contexts + SuppressedContexts, +} + +#[cfg(test)] +pub(crate) mod test_rust_gungraun_json { + // TODO: add tests +} diff --git a/lib/bencher_adapter/src/adapters/rust/gungraun.rs b/lib/bencher_adapter/src/adapters/rust/gungraun/gungraun_text.rs similarity index 94% rename from lib/bencher_adapter/src/adapters/rust/gungraun.rs rename to lib/bencher_adapter/src/adapters/rust/gungraun/gungraun_text.rs index 4b6de0c9f..6d1b86478 100644 --- a/lib/bencher_adapter/src/adapters/rust/gungraun.rs +++ b/lib/bencher_adapter/src/adapters/rust/gungraun/gungraun_text.rs @@ -1,31 +1,31 @@ use std::ops::Neg as _; use bencher_json::{ - BenchmarkName, JsonNewMetric, project::{ - measure::built_in::{BuiltInMeasure as _, gungraun}, + measure::built_in::{gungraun, BuiltInMeasure as _}, report::JsonAverage, }, + BenchmarkName, JsonNewMetric, }; use nom::{ - IResult, branch::alt, bytes::complete::{is_a, is_not, tag, take_until1}, character::complete::{char, space0, space1}, combinator::{map, opt, peek, recognize}, multi::{many0, many1}, sequence::{delimited, preceded, terminated, tuple}, + IResult, }; use crate::{ - Adaptable, Settings, adapters::util::parse_f64, results::adapter_results::{AdapterResults, GungraunMeasure}, + Adaptable, Settings, }; -pub struct AdapterRustGungraun; +pub struct AdapterRustGungraunText; -impl Adaptable for AdapterRustGungraun { +impl Adaptable for AdapterRustGungraunText { fn parse(input: &str, settings: Settings) -> Option { match settings.average { None => {}, @@ -52,8 +52,8 @@ impl Adaptable for AdapterRustGungraun { } } -fn multiple_benchmarks<'a>() --> impl FnMut(&'a str) -> IResult<&'a str, Vec<(BenchmarkName, Vec)>> { +fn multiple_benchmarks<'a>( +) -> impl FnMut(&'a str) -> IResult<&'a str, Vec<(BenchmarkName, Vec)>> { map( many0(alt(( // Try to parse a single benchmark: @@ -68,8 +68,8 @@ fn multiple_benchmarks<'a>() ) } -fn single_benchmark<'a>() --> impl FnMut(&'a str) -> IResult<&'a str, Option<(BenchmarkName, Vec)>> { +fn single_benchmark<'a>( +) -> impl FnMut(&'a str) -> IResult<&'a str, Option<(BenchmarkName, Vec)>> { map( tuple(( terminated( @@ -365,7 +365,11 @@ fn factor(input: &str) -> IResult<&str, f64> { map( tuple((alt((char('+'), char('-'))), parse_f64, char('x'))), |(sign, num, _)| { - if sign == '+' { num } else { num.neg() } + if sign == '+' { + num + } else { + num.neg() + } }, )(input) } @@ -374,7 +378,11 @@ fn percent(input: &str) -> IResult<&str, f64> { map( tuple((alt((char('+'), char('-'))), parse_f64, char('%'))), |(sign, num, _)| { - if sign == '+' { num } else { num.neg() } + if sign == '+' { + num + } else { + num.neg() + } }, )(input) } @@ -407,18 +415,18 @@ fn not_benchmark_name_end<'a>() -> impl FnMut(&'a str) -> IResult<&'a str, &'a s } #[cfg(test)] -pub(crate) mod test_rust_gungraun { - use crate::{AdapterResults, adapters::test_util::convert_file_path}; - use bencher_json::project::measure::built_in::{BuiltInMeasure as _, gungraun}; +pub(crate) mod test_rust_gungraun_text { + use crate::{adapters::test_util::convert_file_path, AdapterResults}; + use bencher_json::project::measure::built_in::{gungraun, BuiltInMeasure as _}; use ordered_float::OrderedFloat; use pretty_assertions::assert_eq; - use super::AdapterRustGungraun; + use super::AdapterRustGungraunText; use std::collections::HashMap; #[test] fn without_optional_metrics() { - let results = convert_file_path::( + let results = convert_file_path::( "./tool_output/rust/gungraun/without-optional-metrics.txt", ); @@ -427,8 +435,9 @@ pub(crate) mod test_rust_gungraun { #[test] fn with_dhat() { - let results = - convert_file_path::("./tool_output/rust/gungraun/with-dhat.txt"); + let results = convert_file_path::( + "./tool_output/rust/gungraun/with-dhat.txt", + ); validate_adapter_rust_gungraun( &results, @@ -441,7 +450,7 @@ pub(crate) mod test_rust_gungraun { #[test] fn with_dhat_first_then_callgrind() { - let results = convert_file_path::( + let results = convert_file_path::( "./tool_output/rust/gungraun/dhat-then-callgrind.txt", ); @@ -456,7 +465,7 @@ pub(crate) mod test_rust_gungraun { #[test] fn with_dhat_and_global_bus_events() { - let results = convert_file_path::( + let results = convert_file_path::( "./tool_output/rust/gungraun/with-dhat-and-global-bus-events.txt", ); @@ -472,14 +481,14 @@ pub(crate) mod test_rust_gungraun { #[test] fn delta() { let results = - convert_file_path::("./tool_output/rust/gungraun/delta.txt"); + convert_file_path::("./tool_output/rust/gungraun/delta.txt"); validate_adapter_rust_gungraun(&results, &OptionalMetrics::default()); } #[test] fn delta_with_infinity() { - let results = convert_file_path::( + let results = convert_file_path::( "./tool_output/rust/gungraun/delta_with_inf.txt", ); @@ -522,7 +531,7 @@ pub(crate) mod test_rust_gungraun { #[test] fn with_summary_and_regressions() { - let results = convert_file_path::( + let results = convert_file_path::( "./tool_output/rust/gungraun/with-summary-and-regressions.txt", ); @@ -531,7 +540,7 @@ pub(crate) mod test_rust_gungraun { #[test] fn with_gungraun_summary() { - let results = convert_file_path::( + let results = convert_file_path::( "./tool_output/rust/gungraun/with-gungraun-summary.txt", ); @@ -540,7 +549,7 @@ pub(crate) mod test_rust_gungraun { #[test] fn ansi_escapes_issue_345() { - let results = convert_file_path::( + let results = convert_file_path::( "./tool_output/rust/gungraun/ansi-escapes.txt", ); @@ -550,7 +559,7 @@ pub(crate) mod test_rust_gungraun { #[test] fn with_ge() { let results = - convert_file_path::("./tool_output/rust/gungraun/with-ge.txt"); + convert_file_path::("./tool_output/rust/gungraun/with-ge.txt"); validate_adapter_rust_gungraun( &results, @@ -565,7 +574,7 @@ pub(crate) mod test_rust_gungraun { fn without_cachesim() { use gungraun::*; - let results = convert_file_path::( + let results = convert_file_path::( "./tool_output/rust/gungraun/without-cachesim.txt", ); @@ -596,7 +605,7 @@ pub(crate) mod test_rust_gungraun { fn callgrind_mixed_order() { use gungraun::*; - let results = convert_file_path::( + let results = convert_file_path::( "./tool_output/rust/gungraun/callgrind-mixed-order.txt", ); @@ -625,7 +634,7 @@ pub(crate) mod test_rust_gungraun { fn callgrind_ll_hits() { use gungraun::*; - let results = convert_file_path::( + let results = convert_file_path::( "./tool_output/rust/gungraun/callgrind-ll-hits.txt", ); @@ -656,7 +665,7 @@ pub(crate) mod test_rust_gungraun { fn callgrind_all() { use gungraun::*; - let results = convert_file_path::( + let results = convert_file_path::( "./tool_output/rust/gungraun/callgrind-all.txt", ); @@ -756,8 +765,9 @@ pub(crate) mod test_rust_gungraun { fn cachegrind() { use gungraun::*; - let results = - convert_file_path::("./tool_output/rust/gungraun/cachegrind.txt"); + let results = convert_file_path::( + "./tool_output/rust/gungraun/cachegrind.txt", + ); assert_eq!(results.inner.len(), 3); @@ -824,8 +834,9 @@ pub(crate) mod test_rust_gungraun { fn memcheck() { use gungraun::*; - let results = - convert_file_path::("./tool_output/rust/gungraun/memcheck.txt"); + let results = convert_file_path::( + "./tool_output/rust/gungraun/memcheck.txt", + ); assert_eq!(results.inner.len(), 3); @@ -874,8 +885,9 @@ pub(crate) mod test_rust_gungraun { fn helgrind() { use gungraun::*; - let results = - convert_file_path::("./tool_output/rust/gungraun/helgrind.txt"); + let results = convert_file_path::( + "./tool_output/rust/gungraun/helgrind.txt", + ); assert_eq!(results.inner.len(), 3); @@ -925,7 +937,7 @@ pub(crate) mod test_rust_gungraun { use gungraun::*; let results = - convert_file_path::("./tool_output/rust/gungraun/drd.txt"); + convert_file_path::("./tool_output/rust/gungraun/drd.txt"); assert_eq!(results.inner.len(), 3); @@ -974,7 +986,7 @@ pub(crate) mod test_rust_gungraun { fn name_multiple_lines() { use gungraun::*; - let results = convert_file_path::( + let results = convert_file_path::( "./tool_output/rust/gungraun/name_on_multiple_lines.txt", ); @@ -1023,7 +1035,7 @@ pub(crate) mod test_rust_gungraun { fn name_multiple_lines_mixed() { use gungraun::*; - let results = convert_file_path::( + let results = convert_file_path::( "./tool_output/rust/gungraun/name_on_multiple_lines_mixed.txt", ); diff --git a/lib/bencher_adapter/src/adapters/rust/gungraun/mod.rs b/lib/bencher_adapter/src/adapters/rust/gungraun/mod.rs new file mode 100644 index 000000000..385adb2ef --- /dev/null +++ b/lib/bencher_adapter/src/adapters/rust/gungraun/mod.rs @@ -0,0 +1,36 @@ +pub mod gungraun_json; +pub mod gungraun_text; + +use crate::{ + adapters::rust::gungraun::{ + gungraun_json::AdapterRustGungraunJson, gungraun_text::AdapterRustGungraunText, + }, + Adaptable, AdapterResults, Settings, +}; + +pub struct AdapterRustGungraun; + +impl Adaptable for AdapterRustGungraun { + fn parse(input: &str, settings: Settings) -> Option { + AdapterRustGungraunJson::parse(input, settings) + .or_else(|| AdapterRustGungraunText::parse(input, settings)) + } +} + +#[cfg(test)] +mod test_rust { + use super::AdapterRustGungraun; + use crate::adapters::test_util::convert_file_path; + + #[test] + fn adapter_rust_gungraun() { + let results = convert_file_path::( + "./tool_output/rust/gungraun/without-optional-metrics.txt", + ); + + // test_rust_gungraun::validate_adapter_rust_gungraun( + // &results, + // &test_rust_gungraun::OptionalMetrics::default(), + // ); + } +} diff --git a/lib/bencher_adapter/src/results/adapter_results.rs b/lib/bencher_adapter/src/results/adapter_results.rs index 39e455d39..f69df920f 100644 --- a/lib/bencher_adapter/src/results/adapter_results.rs +++ b/lib/bencher_adapter/src/results/adapter_results.rs @@ -1,16 +1,16 @@ use std::{collections::HashMap, str::FromStr as _}; use bencher_json::{ - BenchmarkName, JsonNewMetric, project::{ measure::built_in::{self, BuiltInMeasure as _}, metric::Mean, }, + BenchmarkName, JsonNewMetric, }; use literally::hmap; use serde::{Deserialize, Serialize}; -use super::{CombinedKind, adapter_metrics::AdapterMetrics}; +use super::{adapter_metrics::AdapterMetrics, CombinedKind}; #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] pub struct AdapterResults { @@ -42,6 +42,7 @@ pub enum IaiMeasure { } #[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] pub enum GungraunMeasure { /* * Callgrind tool: @@ -88,6 +89,8 @@ pub enum GungraunMeasure { /* * DHAT tool: */ + TotalUnits(JsonNewMetric), + TotalEvents(JsonNewMetric), TotalBytes(JsonNewMetric), TotalBlocks(JsonNewMetric), AtTGmaxBytes(JsonNewMetric), @@ -96,6 +99,9 @@ pub enum GungraunMeasure { AtTEndBlocks(JsonNewMetric), ReadsBytes(JsonNewMetric), WritesBytes(JsonNewMetric), + TotalLifetimes(JsonNewMetric), + MaximumBytes(JsonNewMetric), + MaximumBlocks(JsonNewMetric), /* * Memcheck tool: @@ -343,6 +349,12 @@ impl AdapterResults { (built_in::gungraun::SpLoss2::name_id(), json_metric) }, // DHAT + GungraunMeasure::TotalUnits(json_metric) => { + (built_in::gungraun::TotalUnits::name_id(), json_metric) + }, + GungraunMeasure::TotalEvents(json_metric) => { + (built_in::gungraun::TotalEvents::name_id(), json_metric) + }, GungraunMeasure::TotalBytes(json_metric) => { (built_in::gungraun::TotalBytes::name_id(), json_metric) }, @@ -367,6 +379,15 @@ impl AdapterResults { GungraunMeasure::WritesBytes(json_metric) => { (built_in::gungraun::WritesBytes::name_id(), json_metric) }, + GungraunMeasure::TotalLifetimes(json_metric) => { + (built_in::gungraun::TotalLifetimes::name_id(), json_metric) + }, + GungraunMeasure::MaximumBytes(json_metric) => { + (built_in::gungraun::MaximumBytes::name_id(), json_metric) + }, + GungraunMeasure::MaximumBlocks(json_metric) => { + (built_in::gungraun::MaximumBlocks::name_id(), json_metric) + }, // Memcheck GungraunMeasure::MemcheckErrors(json_metric) => { (built_in::gungraun::MemcheckErrors::name_id(), json_metric) diff --git a/lib/bencher_json/src/project/measure/built_in.rs b/lib/bencher_json/src/project/measure/built_in.rs index 54efe8f31..22f7894f6 100644 --- a/lib/bencher_json/src/project/measure/built_in.rs +++ b/lib/bencher_json/src/project/measure/built_in.rs @@ -152,6 +152,8 @@ pub mod gungraun { create_measure!(SpLoss2, "SpLoss2", "sploss2", "spatial loss count"); // DHAT + create_measure!(TotalUnits, "Total units", "total-units", "units"); + create_measure!(TotalEvents, "Total events", "total-events", "events"); create_measure!(TotalBytes, "Total bytes", "total-bytes", BYTES); create_measure!(TotalBlocks, "Total blocks", "total-blocks", "blocks"); create_measure!(AtTGmaxBytes, "At t-gmax bytes", "at-t-gmax-bytes", BYTES); @@ -165,6 +167,14 @@ pub mod gungraun { create_measure!(AtTEndBlocks, "At t-end blocks", "at-t-end-blocks", "blocks"); create_measure!(ReadsBytes, "Reads bytes", "reads-bytes", BYTES); create_measure!(WritesBytes, "Writes bytes", "writes-bytes", BYTES); + create_measure!( + TotalLifetimes, + "Total lifetimes", + "total-lifetimes", + "lifetimes" + ); + create_measure!(MaximumBytes, "Maximum bytes", "maximum-bytes", BYTES); + create_measure!(MaximumBlocks, "Maximum blocks", "maximum-blocks", "blocks"); // Memcheck create_measure!(