Skip to main content

weir/fixed_point_scratch/
telemetry.rs

1use crate::dense_domain::{
2    plan_sparse_dense_domain, SparseDenseDomainMode, SparseDenseDomainObservation,
3    SparseDenseDomainPolicy,
4};
5
6/// Execution family suggested by observed fixed-point frontier density.
7#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
8pub enum FrontierExecutionMode {
9    /// No active frontier bits were observed.
10    Empty,
11    /// Low active and low delta density; a sparse frontier kernel should win.
12    Sparse,
13    /// Mixed density; a sparse/dense hybrid or adaptive kernel should win.
14    Hybrid,
15    /// High active density; a dense bitset kernel should win.
16    Dense,
17}
18
19/// Frontier density counters captured by a fixed-point scratch session.
20#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
21pub struct FrontierDensityTelemetry {
22    /// Number of bits in the analysis domain for this run.
23    pub domain_bits: u64,
24    /// Number of decoded frontier samples, including the seed frontier.
25    pub samples: u64,
26    /// Number of GPU fixed-point iterations observed.
27    pub iterations: u64,
28    /// Sum of active frontier bits across all samples.
29    pub active_bits_total: u64,
30    /// Sum of changed frontier bits across decoded GPU transitions.
31    pub delta_bits_total: u64,
32    /// Active bits in the most recently decoded frontier sample.
33    pub last_active_bits: u64,
34    /// Changed bits between the previous frontier and the most recent sample.
35    pub last_delta_bits: u64,
36    /// Maximum active bits observed in one frontier sample.
37    pub peak_active_bits: u64,
38    /// Maximum changed bits observed in one decoded GPU transition.
39    pub peak_delta_bits: u64,
40    /// Number of frontier telemetry samples where decoded words were shorter than the domain.
41    pub truncated_frontier_samples: u64,
42    /// Number of times the telemetry domain could not fit the host index width.
43    pub domain_overflow_events: u64,
44    /// Number of telemetry counter additions that pinned at `u64::MAX`.
45    pub arithmetic_overflow_events: u64,
46}
47
48impl FrontierDensityTelemetry {
49    pub(crate) fn begin(domain_bits: u32) -> Self {
50        Self {
51            domain_bits: u64::from(domain_bits),
52            samples: 0,
53            iterations: 0,
54            active_bits_total: 0,
55            delta_bits_total: 0,
56            last_active_bits: 0,
57            last_delta_bits: 0,
58            peak_active_bits: 0,
59            peak_delta_bits: 0,
60            truncated_frontier_samples: 0,
61            domain_overflow_events: 0,
62            arithmetic_overflow_events: 0,
63        }
64    }
65
66    pub(crate) fn record_sample(&mut self, active: u64) {
67        self.samples = bounded_add(self.samples, 1);
68        self.active_bits_total = bounded_add(self.active_bits_total, active);
69        self.last_active_bits = active;
70        self.peak_active_bits = self.peak_active_bits.max(active);
71    }
72
73    pub(crate) fn record_transition(&mut self, active: u64, delta: u64) {
74        self.iterations = bounded_add(self.iterations, 1);
75        self.record_sample(active);
76        self.record_delta(delta);
77    }
78
79    pub(crate) fn record_window(&mut self, iterations: u32, active: u64, delta: u64) {
80        self.iterations = bounded_add(self.iterations, u64::from(iterations));
81        self.record_sample(active);
82        self.record_delta(delta);
83    }
84
85    fn record_delta(&mut self, delta: u64) {
86        self.delta_bits_total = bounded_add(self.delta_bits_total, delta);
87        self.last_delta_bits = delta;
88        self.peak_delta_bits = self.peak_delta_bits.max(delta);
89    }
90
91    /// Malformed frontier decode length (cold error telemetry).
92    #[cold]
93    pub(crate) fn record_truncated_frontier_sample(&mut self) {
94        self.truncated_frontier_samples = bounded_add(self.truncated_frontier_samples, 1);
95    }
96
97    /// Domain bit width overflow (cold error telemetry).
98    #[cold]
99    pub(crate) fn record_domain_overflow(&mut self) {
100        self.domain_overflow_events = bounded_add(self.domain_overflow_events, 1);
101    }
102
103    /// Telemetry counter saturation (cold error telemetry).
104    #[cold]
105    pub(crate) fn record_arithmetic_overflow(&mut self) {
106        self.arithmetic_overflow_events = bounded_add(self.arithmetic_overflow_events, 1);
107    }
108
109    /// Mean active frontier density across all samples in parts per million.
110    #[must_use]
111    pub fn active_density_ppm(self) -> u64 {
112        let denominator = u128::from(self.domain_bits) * u128::from(self.samples);
113        if denominator == 0 {
114            0
115        } else {
116            ppm(self.active_bits_total, denominator)
117        }
118    }
119
120    /// Mean changed-frontier density across decoded GPU transitions in parts per million.
121    #[must_use]
122    pub fn delta_density_ppm(self) -> u64 {
123        let denominator = u128::from(self.domain_bits) * u128::from(self.iterations);
124        if denominator == 0 {
125            0
126        } else {
127            ppm(self.delta_bits_total, denominator)
128        }
129    }
130
131    /// Density of the latest decoded frontier sample in parts per million.
132    #[must_use]
133    pub fn last_active_density_ppm(self) -> u64 {
134        if self.domain_bits == 0 {
135            0
136        } else {
137            ppm(self.last_active_bits, u128::from(self.domain_bits))
138        }
139    }
140
141    /// Density of the latest decoded frontier delta in parts per million.
142    #[must_use]
143    pub fn last_delta_density_ppm(self) -> u64 {
144        if self.domain_bits == 0 {
145            0
146        } else {
147            ppm(self.last_delta_bits, u128::from(self.domain_bits))
148        }
149    }
150
151    /// Choose a sparse, dense, or hybrid execution family from measured density.
152    #[must_use]
153    pub fn recommended_execution_mode(self) -> FrontierExecutionMode {
154        let plan = plan_sparse_dense_domain(
155            SparseDenseDomainPolicy::frontier_density(),
156            SparseDenseDomainObservation {
157                domain_bits: self.domain_bits,
158                samples: self.samples,
159                iterations: self.iterations,
160                active_bits_total: self.active_bits_total,
161                delta_bits_total: self.delta_bits_total,
162                last_active_bits: self.last_active_bits,
163                peak_active_bits: self.peak_active_bits,
164                average_degree_ppm: 0,
165            },
166        );
167        match plan.mode {
168            SparseDenseDomainMode::Empty => FrontierExecutionMode::Empty,
169            SparseDenseDomainMode::Sparse => FrontierExecutionMode::Sparse,
170            SparseDenseDomainMode::Hybrid => FrontierExecutionMode::Hybrid,
171            SparseDenseDomainMode::Dense => FrontierExecutionMode::Dense,
172        }
173    }
174}
175
176fn bounded_add(left: u64, right: u64) -> u64 {
177    #[allow(clippy::manual_saturating_arithmetic)]
178    left.checked_add(right).unwrap_or(u64::MAX)
179}
180
181fn ppm(numerator: u64, denominator: u128) -> u64 {
182    let scaled = u128::from(numerator) * 1_000_000;
183    let value = scaled / denominator;
184    if value > u128::from(u64::MAX) {
185        u64::MAX
186    } else {
187        value as u64
188    }
189}
190
191#[cfg(test)]
192mod tests {
193    use super::*;
194
195    #[test]
196    fn frontier_density_telemetry_does_not_panic_on_counter_overflow() {
197        let mut telemetry = FrontierDensityTelemetry {
198            domain_bits: u64::from(u32::MAX),
199            samples: u64::MAX,
200            iterations: u64::MAX,
201            active_bits_total: u64::MAX,
202            delta_bits_total: u64::MAX,
203            last_active_bits: 0,
204            last_delta_bits: 0,
205            peak_active_bits: 0,
206            peak_delta_bits: 0,
207            truncated_frontier_samples: 0,
208            domain_overflow_events: 0,
209            arithmetic_overflow_events: 0,
210        };
211
212        telemetry.record_transition(u64::MAX, u64::MAX);
213        telemetry.record_window(u32::MAX, u64::MAX, u64::MAX);
214
215        assert_eq!(telemetry.samples, u64::MAX);
216        assert_eq!(telemetry.iterations, u64::MAX);
217        assert_eq!(telemetry.active_bits_total, u64::MAX);
218        assert_eq!(telemetry.delta_bits_total, u64::MAX);
219        telemetry.record_truncated_frontier_sample();
220        telemetry.record_domain_overflow();
221        telemetry.record_arithmetic_overflow();
222        assert_eq!(telemetry.truncated_frontier_samples, 1);
223        assert_eq!(telemetry.domain_overflow_events, 1);
224        assert_eq!(telemetry.arithmetic_overflow_events, 1);
225        let _ = telemetry.active_density_ppm();
226        let _ = telemetry.delta_density_ppm();
227        assert!(telemetry.last_active_density_ppm() > 1_000_000);
228        assert!(telemetry.last_delta_density_ppm() > 1_000_000);
229    }
230
231    #[test]
232    fn frontier_density_telemetry_source_has_no_panic_arithmetic() {
233        let source = include_str!("telemetry.rs");
234        let production = source
235            .split("#[cfg(test)]")
236            .next()
237            .expect("telemetry production source must precede tests");
238        assert!(
239            !production.contains(concat!("panic", "!("))
240                && !production.contains(".unwrap_or_else(")
241                && !production.contains(concat!(".", "saturating_add")),
242            "Fix: fixed-point frontier telemetry must not abort or hide overflow with saturating arithmetic."
243        );
244        assert!(
245            production.contains("u128::from(self.domain_bits) * u128::from(self.samples)")
246                && production.contains("fn bounded_add(")
247                && production.contains("record_truncated_frontier_sample"),
248            "Fix: fixed-point frontier telemetry must use widened density math and bounded explicit counter updates."
249        );
250    }
251}