cu_profiler_core/baseline/
compare.rs1use serde::{Deserialize, Serialize};
4
5use crate::baseline::fingerprint::Fingerprint;
6use crate::model::Measurement;
7
8#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
10pub struct BaselineComparison {
11 pub matched: bool,
13 #[serde(default, skip_serializing_if = "Vec::is_empty")]
15 pub stale_reasons: Vec<String>,
16 pub baseline_units: u64,
18 pub current_units: u64,
20 pub delta_units: i64,
22 pub delta_pct: f64,
24}
25
26impl BaselineComparison {
27 #[must_use]
30 pub fn compute(
31 baseline_units: u64,
32 baseline_fp: &Fingerprint,
33 current: &Measurement,
34 current_fp: &Fingerprint,
35 ) -> Self {
36 let stale_reasons = baseline_fp.staleness_reasons(current_fp);
37 let current_units = current.total_cu;
38 let delta_units = current_units as i64 - baseline_units as i64;
39 let delta_pct = if baseline_units == 0 {
40 0.0
41 } else {
42 (delta_units as f64 / baseline_units as f64) * 100.0
43 };
44 Self {
45 matched: stale_reasons.is_empty(),
46 stale_reasons,
47 baseline_units,
48 current_units,
49 delta_units,
50 delta_pct,
51 }
52 }
53
54 #[must_use]
56 pub fn summary(&self) -> String {
57 format!(
58 "{:+.2}% ({:+} CU) vs baseline {}",
59 self.delta_pct, self.delta_units, self.baseline_units
60 )
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67
68 fn fp(fixture: &str) -> Fingerprint {
69 Fingerprint::new("s", fixture, "cfg", None)
70 }
71
72 fn measurement(cu: u64) -> Measurement {
73 Measurement {
74 total_cu: cu,
75 ..Measurement::empty()
76 }
77 }
78
79 #[test]
80 fn matched_comparison_reports_delta() {
81 let c = BaselineComparison::compute(91_204, &fp("a"), &measurement(96_812), &fp("a"));
82 assert!(c.matched);
83 assert_eq!(c.delta_units, 5_608);
84 assert!((c.delta_pct - 6.15).abs() < 0.01);
85 }
86
87 #[test]
88 fn changed_fixture_is_stale() {
89 let c = BaselineComparison::compute(91_204, &fp("a"), &measurement(96_812), &fp("b"));
90 assert!(!c.matched);
91 assert!(c.stale_reasons.iter().any(|r| r.contains("fixture hash")));
92 }
93}