Repository: bencherdev/bencher (language: rust)

Issue:
Track global bus events for iai-callgrind
Track global bus events for iai-callgrind: https://github.com/iai-callgrind/iai-callgrind/issues/93

@OmarTawfik any interest in implementing this to round out https://github.com/bencherdev/bencher/pull/461?


Discussion / hints:

Fix patch:
diff --git a/lib/bencher_adapter/src/adapters/magic.rs b/lib/bencher_adapter/src/adapters/magic.rs
index 3482f09b5..f6b619165 100644
--- a/lib/bencher_adapter/src/adapters/magic.rs
+++ b/lib/bencher_adapter/src/adapters/magic.rs
@@ -133,9 +133,14 @@ mod test_magic {
 
     #[test]
     fn test_adapter_magic_rust_iai_callgrind() {
-        let results =
-            convert_file_path::<AdapterMagic>("./tool_output/rust/iai_callgrind/single-tool.txt");
-        test_rust_iai_callgrind::validate_adapter_rust_iai_callgrind(&results, true, false);
+        let results = convert_file_path::<AdapterMagic>(
+            "./tool_output/rust/iai_callgrind/without-optional-metrics.txt",
+        );
+
+        test_rust_iai_callgrind::validate_adapter_rust_iai_callgrind(
+            &results,
+            &test_rust_iai_callgrind::OptionalMetrics::default(),
+        );
     }
 
     #[test]
diff --git a/lib/bencher_adapter/src/adapters/rust/iai_callgrind.rs b/lib/bencher_adapter/src/adapters/rust/iai_callgrind.rs
index c7fe08e2a..6c756a929 100644
--- a/lib/bencher_adapter/src/adapters/rust/iai_callgrind.rs
+++ b/lib/bencher_adapter/src/adapters/rust/iai_callgrind.rs
@@ -103,17 +103,30 @@ fn callgrind_tool_measures<'a>() -> impl FnMut(&'a str) -> IResult<&'a str, Vec<
                 metric_line(callgrind_tool::RamHits::NAME_STR),
                 metric_line(callgrind_tool::TotalReadWrite::NAME_STR),
                 metric_line(callgrind_tool::EstimatedCycles::NAME_STR),
+                opt(metric_line(callgrind_tool::GlobalBusEvents::NAME_STR)),
             )),
         ),
-        |(instructions, l1_hits, l2_hits, ram_hits, total_read_write, estimated_cycles)| {
-            vec![
-                IaiCallgrindMeasure::Instructions(instructions),
-                IaiCallgrindMeasure::L1Hits(l1_hits),
-                IaiCallgrindMeasure::L2Hits(l2_hits),
-                IaiCallgrindMeasure::RamHits(ram_hits),
-                IaiCallgrindMeasure::TotalReadWrite(total_read_write),
-                IaiCallgrindMeasure::EstimatedCycles(estimated_cycles),
+        |(
+            instructions,
+            l1_hits,
+            l2_hits,
+            ram_hits,
+            total_read_write,
+            estimated_cycles,
+            global_bus_events,
+        )| {
+            [
+                Some(IaiCallgrindMeasure::Instructions(instructions)),
+                Some(IaiCallgrindMeasure::L1Hits(l1_hits)),
+                Some(IaiCallgrindMeasure::L2Hits(l2_hits)),
+                Some(IaiCallgrindMeasure::RamHits(ram_hits)),
+                Some(IaiCallgrindMeasure::TotalReadWrite(total_read_write)),
+                Some(IaiCallgrindMeasure::EstimatedCycles(estimated_cycles)),
+                global_bus_events.map(IaiCallgrindMeasure::GlobalBusEvents),
             ]
+            .into_iter()
+            .flatten()
+            .collect()
         },
     )
 }
@@ -236,60 +249,106 @@ pub(crate) mod test_rust_iai_callgrind {
     use std::collections::HashMap;
 
     #[test]
-    fn test_iai_adapter_single_tool() {
+    fn test_without_optional_metrics() {
         let results = convert_file_path::<AdapterRustIaiCallgrind>(
-            "./tool_output/rust/iai_callgrind/single-tool.txt",
+            "./tool_output/rust/iai_callgrind/without-optional-metrics.txt",
         );
 
-        validate_adapter_rust_iai_callgrind(&results, true, false);
+        validate_adapter_rust_iai_callgrind(&results, &OptionalMetrics::default());
     }
 
     #[test]
-    fn test_iai_adapter_multiple_tools() {
+    fn test_with_dhat() {
         let results = convert_file_path::<AdapterRustIaiCallgrind>(
-            "./tool_output/rust/iai_callgrind/multiple-tools.txt",
+            "./tool_output/rust/iai_callgrind/with-dhat.txt",
+        );
+
+        validate_adapter_rust_iai_callgrind(
+            &results,
+            &OptionalMetrics {
+                dhat: true,
+                ..Default::default()
+            },
         );
-        validate_adapter_rust_iai_callgrind(&results, true, true);
     }
 
     #[test]
-    fn test_iai_adapter_delta() {
+    fn test_with_dhat_and_global_bus_events() {
+        let results = convert_file_path::<AdapterRustIaiCallgrind>(
+            "./tool_output/rust/iai_callgrind/with-dhat-and-global-bus-events.txt",
+        );
+
+        validate_adapter_rust_iai_callgrind(
+            &results,
+            &OptionalMetrics {
+                dhat: true,
+                global_bus_events: true,
+            },
+        );
+    }
+
+    #[test]
+    fn test_delta() {
         let results = convert_file_path::<AdapterRustIaiCallgrind>(
             "./tool_output/rust/iai_callgrind/delta.txt",
         );
-        validate_adapter_rust_iai_callgrind(&results, true, false);
+
+        validate_adapter_rust_iai_callgrind(&results, &OptionalMetrics::default());
     }
 
     #[test]
-    fn test_iai_adapter_ansi_escapes_issue_345() {
+    fn test_ansi_escapes_issue_345() {
         let results = convert_file_path::<AdapterRustIaiCallgrind>(
             "./tool_output/rust/iai_callgrind/ansi-escapes.txt",
         );
-        validate_adapter_rust_iai_callgrind(&results, true, false);
+
+        validate_adapter_rust_iai_callgrind(&results, &OptionalMetrics::default());
+    }
+
+    #[test]
+    fn test_with_ge() {
+        let results = convert_file_path::<AdapterRustIaiCallgrind>(
+            "./tool_output/rust/iai_callgrind/with-ge.txt",
+        );
+
+        validate_adapter_rust_iai_callgrind(
+            &results,
+            &OptionalMetrics {
+                global_bus_events: true,
+                ..Default::default()
+            },
+        );
+    }
+
+    #[derive(Default)]
+    pub struct OptionalMetrics {
+        pub global_bus_events: bool,
+        pub dhat: bool,
     }
 
     pub fn validate_adapter_rust_iai_callgrind(
         results: &AdapterResults,
-        callgrind_tool: bool,
-        dhat_tool: bool,
+        optional_metrics: &OptionalMetrics,
     ) {
         assert_eq!(results.inner.len(), 2);
 
         {
             let mut expected = HashMap::new();
 
-            if callgrind_tool {
-                expected.extend([
-                    (callgrind_tool::Instructions::SLUG_STR, 1_734.0),
-                    (callgrind_tool::L1Hits::SLUG_STR, 2_359.0),
-                    (callgrind_tool::L2Hits::SLUG_STR, 0.0),
-                    (callgrind_tool::RamHits::SLUG_STR, 3.0),
-                    (callgrind_tool::TotalReadWrite::SLUG_STR, 2_362.0),
-                    (callgrind_tool::EstimatedCycles::SLUG_STR, 2_464.0),
-                ]);
+            expected.extend([
+                (callgrind_tool::Instructions::SLUG_STR, 1_734.0),
+                (callgrind_tool::L1Hits::SLUG_STR, 2_359.0),
+                (callgrind_tool::L2Hits::SLUG_STR, 0.0),
+                (callgrind_tool::RamHits::SLUG_STR, 3.0),
+                (callgrind_tool::TotalReadWrite::SLUG_STR, 2_362.0),
+                (callgrind_tool::EstimatedCycles::SLUG_STR, 2_464.0),
+            ]);
+
+            if optional_metrics.global_bus_events {
+                expected.insert(callgrind_tool::GlobalBusEvents::SLUG_STR, 2.0);
             }
 
-            if dhat_tool {
+            if optional_metrics.dhat {
                 expected.extend([
                     (dhat_tool::TotalBytes::SLUG_STR, 29_499.0),
                     (dhat_tool::TotalBlocks::SLUG_STR, 2_806.0),
@@ -312,18 +371,20 @@ pub(crate) mod test_rust_iai_callgrind {
         {
             let mut expected = HashMap::new();
 
-            if callgrind_tool {
-                expected.extend([
-                    (callgrind_tool::Instructions::SLUG_STR, 26_214_734.0),
-                    (callgrind_tool::L1Hits::SLUG_STR, 35_638_619.0),
-                    (callgrind_tool::L2Hits::SLUG_STR, 0.0),
-                    (callgrind_tool::RamHits::SLUG_STR, 3.0),
-                    (callgrind_tool::TotalReadWrite::SLUG_STR, 35_638_622.0),
-                    (callgrind_tool::EstimatedCycles::SLUG_STR, 35_638_724.0),
-                ]);
+            expected.extend([
+                (callgrind_tool::Instructions::SLUG_STR, 26_214_734.0),
+                (callgrind_tool::L1Hits::SLUG_STR, 35_638_619.0),
+                (callgrind_tool::L2Hits::SLUG_STR, 0.0),
+                (callgrind_tool::RamHits::SLUG_STR, 3.0),
+                (callgrind_tool::TotalReadWrite::SLUG_STR, 35_638_622.0),
+                (callgrind_tool::EstimatedCycles::SLUG_STR, 35_638_724.0),
+            ]);
+
+            if optional_metrics.global_bus_events {
+                expected.insert(callgrind_tool::GlobalBusEvents::SLUG_STR, 10.0);
             }
 
-            if dhat_tool {
+            if optional_metrics.dhat {
                 expected.extend([
                     (dhat_tool::TotalBytes::SLUG_STR, 26_294_939.0),
                     (dhat_tool::TotalBlocks::SLUG_STR, 2_328_086.0),
diff --git a/lib/bencher_adapter/src/adapters/rust/mod.rs b/lib/bencher_adapter/src/adapters/rust/mod.rs
index efe8e8219..0d0b814e8 100644
--- a/lib/bencher_adapter/src/adapters/rust/mod.rs
+++ b/lib/bencher_adapter/src/adapters/rust/mod.rs
@@ -51,8 +51,13 @@ mod test_rust {
 
     #[test]
     fn test_adapter_rust_iai_callgrind() {
-        let results =
-            convert_file_path::<AdapterRust>("./tool_output/rust/iai_callgrind/single-tool.txt");
-        test_rust_iai_callgrind::validate_adapter_rust_iai_callgrind(&results, true, false);
+        let results = convert_file_path::<AdapterRust>(
+            "./tool_output/rust/iai_callgrind/without-optional-metrics.txt",
+        );
+
+        test_rust_iai_callgrind::validate_adapter_rust_iai_callgrind(
+            &results,
+            &test_rust_iai_callgrind::OptionalMetrics::default(),
+        );
     }
 }
diff --git a/lib/bencher_adapter/src/results/adapter_results.rs b/lib/bencher_adapter/src/results/adapter_results.rs
index b85a04e71..4a42b31b8 100644
--- a/lib/bencher_adapter/src/results/adapter_results.rs
+++ b/lib/bencher_adapter/src/results/adapter_results.rs
@@ -52,6 +52,7 @@ pub enum IaiCallgrindMeasure {
     RamHits(JsonNewMetric),
     TotalReadWrite(JsonNewMetric),
     EstimatedCycles(JsonNewMetric),
+    GlobalBusEvents(JsonNewMetric),
 
     /*
      * DHAT tool:
@@ -192,6 +193,10 @@ impl AdapterResults {
                         built_in::iai_callgrind::callgrind_tool::EstimatedCycles::name_id(),
                         json_metric,
                     ),
+                    IaiCallgrindMeasure::GlobalBusEvents(json_metric) => (
+                        built_in::iai_callgrind::callgrind_tool::GlobalBusEvents::name_id(),
+                        json_metric,
+                    ),
 
                     /*
                      * DHAT tool:
diff --git a/lib/bencher_adapter/tool_output/rust/iai_callgrind/with-dhat-and-global-bus-events.txt b/lib/bencher_adapter/tool_output/rust/iai_callgrind/with-dhat-and-global-bus-events.txt
new file mode 100644
index 000000000..8a8c707d0
--- /dev/null
+++ b/lib/bencher_adapter/tool_output/rust/iai_callgrind/with-dhat-and-global-bus-events.txt
@@ -0,0 +1,53 @@
+
+running 0 tests
+
+test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+
+rust_iai_callgrind::bench_fibonacci_group::bench_fibonacci short:10
+  ======= CALLGRIND =======================================================
+  Instructions:                1734|N/A             (*********)
+  L1 Hits:                     2359|N/A             (*********)
+  L2 Hits:                        0|N/A             (*********)
+  RAM Hits:                       3|N/A             (*********)
+  Total read+write:            2362|N/A             (*********)
+  Estimated Cycles:            2464|N/A             (*********)
+  Ge:                             2|N/A             (*********)
+  ======= DHAT ============================================================
+  Total bytes:                29499|N/A             (*********)
+  Total blocks:                2806|N/A             (*********)
+  At t-gmax bytes:              378|N/A             (*********)
+  At t-gmax blocks:              34|N/A             (*********)
+  At t-end bytes:                 0|N/A             (*********)
+  At t-end blocks:                0|N/A             (*********)
+  Reads bytes:                57725|N/A             (*********)
+  Writes bytes:               73810|N/A             (*********)
+rust_iai_callgrind::bench_fibonacci_group::bench_fibonacci long:30
+  ======= CALLGRIND =======================================================
+  Instructions:            26214734|N/A             (*********)
+  L1 Hits:                 35638619|N/A             (*********)
+  L2 Hits:                        0|N/A             (*********)
+  RAM Hits:                       3|N/A             (*********)
+  Total read+write:        35638622|N/A             (*********)
+  Estimated Cycles:        35638724|N/A             (*********)
+  Ge:                            10|N/A             (*********)
+  ======= DHAT ============================================================
+  Total bytes:             26294939|N/A             (*********)
+  Total blocks:             2328086|N/A             (*********)
+  At t-gmax bytes:           933718|N/A             (*********)
+  At t-gmax blocks:           18344|N/A             (*********)
+  At t-end bytes:                 0|N/A             (*********)
+  At t-end blocks:                0|N/A             (*********)
+  Reads bytes:             47577425|N/A             (*********)
+  Writes bytes:            37733810|N/A             (*********)
+
+
+
+
+
+
+
+
+
+.... Some trailing text that should be ignored ...
+.... Some trailing text that should be ignored ...
+.... Some trailing text that should be ignored ...
diff --git a/lib/bencher_adapter/tool_output/rust/iai_callgrind/multiple-tools.txt b/lib/bencher_adapter/tool_output/rust/iai_callgrind/with-dhat.txt
similarity index 100%
rename from lib/bencher_adapter/tool_output/rust/iai_callgrind/multiple-tools.txt
rename to lib/bencher_adapter/tool_output/rust/iai_callgrind/with-dhat.txt
diff --git a/lib/bencher_adapter/tool_output/rust/iai_callgrind/with-ge.txt b/lib/bencher_adapter/tool_output/rust/iai_callgrind/with-ge.txt
new file mode 100644
index 000000000..7069e8687
--- /dev/null
+++ b/lib/bencher_adapter/tool_output/rust/iai_callgrind/with-ge.txt
@@ -0,0 +1,21 @@
+
+running 0 tests
+
+test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+
+rust_iai_callgrind::bench_fibonacci_group::bench_fibonacci short:10
+  Instructions:                1734|N/A             (*********)
+  L1 Hits:                     2359|N/A             (*********)
+  L2 Hits:                        0|N/A             (*********)
+  RAM Hits:                       3|N/A             (*********)
+  Total read+write:            2362|N/A             (*********)
+  Estimated Cycles:            2464|N/A             (*********)
+  Ge:                             2|N/A             (*********)
+rust_iai_callgrind::bench_fibonacci_group::bench_fibonacci long:30
+  Instructions:            26214734|N/A             (*********)
+  L1 Hits:                 35638619|N/A             (*********)
+  L2 Hits:                        0|N/A             (*********)
+  RAM Hits:                       3|N/A             (*********)
+  Total read+write:        35638622|N/A             (*********)
+  Estimated Cycles:        35638724|N/A             (*********)
+  Ge:                            10|N/A             (*********)
diff --git a/lib/bencher_adapter/tool_output/rust/iai_callgrind/single-tool.txt b/lib/bencher_adapter/tool_output/rust/iai_callgrind/without-optional-metrics.txt
similarity index 100%
rename from lib/bencher_adapter/tool_output/rust/iai_callgrind/single-tool.txt
rename to lib/bencher_adapter/tool_output/rust/iai_callgrind/without-optional-metrics.txt
diff --git a/lib/bencher_json/src/project/measure/built_in.rs b/lib/bencher_json/src/project/measure/built_in.rs
index 9e14bf025..d5e669fc6 100644
--- a/lib/bencher_json/src/project/measure/built_in.rs
+++ b/lib/bencher_json/src/project/measure/built_in.rs
@@ -96,6 +96,8 @@ pub mod iai_callgrind {
             "estimated-cycles",
             "cycles"
         );
+
+        create_measure!(GlobalBusEvents, "Ge", "global-bus-events", "events");
     }
 
     pub mod dhat_tool {
diff --git a/services/api/src/model/project/measure.rs b/services/api/src/model/project/measure.rs
index 60fa2efec..53c8bcc73 100644
--- a/services/api/src/model/project/measure.rs
+++ b/services/api/src/model/project/measure.rs
@@ -108,6 +108,9 @@ impl QueryMeasure {
             .or_else(|| {
                 built_in::iai_callgrind::callgrind_tool::EstimatedCycles::from_str(measure_str)
             })
+            .or_else(|| {
+                built_in::iai_callgrind::callgrind_tool::GlobalBusEvents::from_str(measure_str)
+            })
             .or_else(|| built_in::iai_callgrind::dhat_tool::TotalBytes::from_str(measure_str))
             .or_else(|| built_in::iai_callgrind::dhat_tool::TotalBlocks::from_str(measure_str))
             .or_else(|| built_in::iai_callgrind::dhat_tool::AtTGmaxBytes::from_str(measure_str))


Test patch: