iai_callgrind_runner/runner/cachegrind/
regression.rs1use indexmap::{IndexMap, IndexSet};
3
4use crate::api::{self, CachegrindMetric};
5use crate::runner::metrics::{Metric, MetricKind, MetricsSummary};
6use crate::runner::summary::ToolRegression;
7use crate::runner::tool::regression::RegressionConfig;
8
9#[derive(Debug, Clone, PartialEq)]
11pub struct CachegrindRegressionConfig {
12 pub fail_fast: bool,
14 pub hard_limits: Vec<(CachegrindMetric, Metric)>,
16 pub soft_limits: Vec<(CachegrindMetric, f64)>,
18}
19
20impl Default for CachegrindRegressionConfig {
21 fn default() -> Self {
22 Self {
23 soft_limits: vec![(CachegrindMetric::Ir, 10f64)],
24 hard_limits: Vec::default(),
25 fail_fast: false,
26 }
27 }
28}
29
30impl RegressionConfig<CachegrindMetric> for CachegrindRegressionConfig {
31 fn check(&self, metrics_summary: &MetricsSummary<CachegrindMetric>) -> Vec<ToolRegression> {
32 self.check_regressions(metrics_summary)
33 .into_iter()
34 .map(|regressions| ToolRegression::with(MetricKind::Cachegrind, regressions))
35 .collect()
36 }
37
38 fn get_soft_limits(&self) -> &[(CachegrindMetric, f64)] {
39 &self.soft_limits
40 }
41
42 fn get_hard_limits(&self) -> &[(CachegrindMetric, Metric)] {
43 &self.hard_limits
44 }
45}
46
47impl TryFrom<api::CachegrindRegressionConfig> for CachegrindRegressionConfig {
48 type Error = String;
49
50 fn try_from(value: api::CachegrindRegressionConfig) -> Result<Self, Self::Error> {
51 let api::CachegrindRegressionConfig {
52 soft_limits,
53 hard_limits,
54 fail_fast,
55 } = value;
56
57 let (soft_limits, hard_limits) = if soft_limits.is_empty() && hard_limits.is_empty() {
58 (
59 IndexMap::from([(CachegrindMetric::Ir, 10f64)]),
60 IndexMap::new(),
61 )
62 } else {
63 let hard_limits = hard_limits
64 .into_iter()
65 .flat_map(|(cachegrind_metrics, metric)| {
66 IndexSet::from(cachegrind_metrics)
67 .into_iter()
68 .map(move |metric_kind| {
69 Metric::from(metric)
70 .try_convert(metric_kind)
71 .ok_or_else(|| {
72 format!(
73 "Invalid hard limit for \
74 '{metric_kind:?}/{cachegrind_metrics:?}': Expected a \
75 'Int' but found '{metric:?}'"
76 )
77 })
78 })
79 })
80 .collect::<Result<IndexMap<CachegrindMetric, Metric>, String>>()?;
81
82 let soft_limits = soft_limits
83 .into_iter()
84 .flat_map(|(m, l)| IndexSet::from(m).into_iter().map(move |e| (e, l)))
85 .collect::<IndexMap<_, _>>();
86
87 (soft_limits, hard_limits)
88 };
89
90 Ok(Self {
91 soft_limits: soft_limits.into_iter().collect(),
92 hard_limits: hard_limits.into_iter().collect(),
93 fail_fast: fail_fast.unwrap_or(false),
94 })
95 }
96}