iai_callgrind_runner/runner/cachegrind/
model.rs1use std::borrow::Cow;
3
4use anyhow::Result;
5use indexmap::indexmap;
6
7use crate::api::CachegrindMetric;
8use crate::runner::callgrind::{CacheSummary, CyclesEstimator};
9use crate::runner::metrics::{Metric, Summarize};
10
11pub type Metrics = crate::runner::metrics::Metrics<CachegrindMetric>;
13
14impl TryFrom<&Metrics> for CacheSummary {
15 type Error = anyhow::Error;
16
17 fn try_from(value: &Metrics) -> std::result::Result<Self, Self::Error> {
18 use CachegrindMetric::*;
19 let estimator = CyclesEstimator::new(
20 value.try_metric_by_kind(&Ir)?,
21 value.try_metric_by_kind(&Dr)?,
22 value.try_metric_by_kind(&Dw)?,
23 value.try_metric_by_kind(&I1mr)?,
24 value.try_metric_by_kind(&D1mr)?,
25 value.try_metric_by_kind(&D1mw)?,
26 value.try_metric_by_kind(&ILmr)?,
27 value.try_metric_by_kind(&DLmr)?,
28 value.try_metric_by_kind(&DLmw)?,
29 );
30
31 Ok(estimator.calculate())
32 }
33}
34
35impl Summarize for CachegrindMetric {
36 fn summarize(costs: &mut Cow<Metrics>) {
37 if !costs.is_summarized() {
38 let _ = costs.to_mut().make_summary();
39 }
40 }
41}
42
43impl Metrics {
44 pub fn make_summary(&mut self) -> Result<()> {
53 let CacheSummary {
54 l1_hits,
55 l3_hits,
56 ram_hits,
57 total_memory_rw,
58 cycles,
59 i1_miss_rate,
60 d1_miss_rate,
61 ll_miss_rate,
62 lli_miss_rate,
63 lld_miss_rate,
64 l1_hit_rate,
65 l3_hit_rate,
66 ram_hit_rate,
67 } = (&*self).try_into()?;
68
69 self.insert(CachegrindMetric::L1hits, l1_hits);
70 self.insert(CachegrindMetric::LLhits, l3_hits);
71 self.insert(CachegrindMetric::RamHits, ram_hits);
72 self.insert(CachegrindMetric::TotalRW, total_memory_rw);
73 self.insert(CachegrindMetric::EstimatedCycles, cycles);
74 self.insert(CachegrindMetric::I1MissRate, i1_miss_rate);
75 self.insert(CachegrindMetric::D1MissRate, d1_miss_rate);
76 self.insert(CachegrindMetric::LLiMissRate, lli_miss_rate);
77 self.insert(CachegrindMetric::LLdMissRate, lld_miss_rate);
78 self.insert(CachegrindMetric::LLMissRate, ll_miss_rate);
79 self.insert(CachegrindMetric::L1HitRate, l1_hit_rate);
80 self.insert(CachegrindMetric::LLHitRate, l3_hit_rate);
81 self.insert(CachegrindMetric::RamHitRate, ram_hit_rate);
82
83 Ok(())
84 }
85
86 pub fn is_summarized(&self) -> bool {
90 self.metric_by_kind(&CachegrindMetric::EstimatedCycles)
91 .is_some()
92 }
93
94 pub fn can_summarize(&self) -> bool {
99 self.metric_by_kind(&CachegrindMetric::I1mr).is_some()
100 }
101}
102
103impl Default for Metrics {
104 fn default() -> Self {
105 Self(indexmap! {CachegrindMetric::Ir => Metric::Int(0)})
106 }
107}
108
109#[cfg(test)]
110mod tests {
111 use super::*;
112
113 #[test]
116 fn test_metrics_make_summary_when_cache_sim() {
117 use CachegrindMetric::*;
118
119 let mut expected = Metrics::with_metric_kinds([
120 (Ir, 1),
121 (Dr, 2),
122 (Dw, 3),
123 (I1mr, 4),
124 (D1mr, 5),
125 (D1mw, 6),
126 (ILmr, 7),
127 (DLmr, 8),
128 (DLmw, 9),
129 (L1hits, 0),
130 (LLhits, 0),
131 (RamHits, 24),
132 (TotalRW, 6),
133 (EstimatedCycles, 840),
134 ]);
135
136 expected.insert_all(&[
137 (I1MissRate, Metric::Float(400.0f64)),
138 (D1MissRate, Metric::Float(220.000_000_000_000_03_f64)),
139 (LLiMissRate, Metric::Float(700.0f64)),
140 (LLdMissRate, Metric::Float(340.0f64)),
141 (LLMissRate, Metric::Float(400.0f64)),
142 (L1HitRate, Metric::Float(0.0f64)),
143 (LLHitRate, Metric::Float(0.0f64)),
144 (RamHitRate, Metric::Float(400.0f64)),
145 ]);
146
147 let mut metrics = Metrics::with_metric_kinds([
148 (Ir, 1),
149 (Dr, 2),
150 (Dw, 3),
151 (I1mr, 4),
152 (D1mr, 5),
153 (D1mw, 6),
154 (ILmr, 7),
155 (DLmr, 8),
156 (DLmw, 9),
157 ]);
158
159 metrics.make_summary().unwrap();
160
161 assert_eq!(metrics, expected);
162 }
163}