Skip to main content

murk_engine/
metrics.rs

1//! Per-tick performance metrics for the simulation engine.
2//!
3//! [`StepMetrics`] captures timing and memory data for a single tick,
4//! enabling telemetry, profiling, and adaptive backoff decisions.
5
6/// Timing and memory metrics collected during a single tick.
7///
8/// All durations are in microseconds. The engine populates these fields
9/// after each `step()` call; consumers (telemetry, backoff logic) read
10/// them from the most recent tick.
11#[derive(Clone, Debug, Default)]
12pub struct StepMetrics {
13    /// Wall-clock time for the entire tick, in microseconds.
14    pub total_us: u64,
15    /// Time spent processing the ingress command queue, in microseconds.
16    pub command_processing_us: u64,
17    /// Per-propagator execution times: `(name, microseconds)`.
18    pub propagator_us: Vec<(String, u64)>,
19    /// Time spent publishing the snapshot to the ring buffer, in microseconds.
20    pub snapshot_publish_us: u64,
21    /// Memory usage of the arena after the tick, in bytes.
22    pub memory_bytes: usize,
23    /// Number of sparse segment ranges available for reuse.
24    pub sparse_retired_ranges: u32,
25    /// Number of sparse segment ranges pending promotion (freed this tick).
26    pub sparse_pending_retired: u32,
27}
28
29#[cfg(test)]
30mod tests {
31    use super::*;
32
33    #[test]
34    fn default_metrics_are_zero() {
35        let m = StepMetrics::default();
36        assert_eq!(m.total_us, 0);
37        assert_eq!(m.command_processing_us, 0);
38        assert!(m.propagator_us.is_empty());
39        assert_eq!(m.snapshot_publish_us, 0);
40        assert_eq!(m.memory_bytes, 0);
41        assert_eq!(m.sparse_retired_ranges, 0);
42        assert_eq!(m.sparse_pending_retired, 0);
43    }
44
45    #[test]
46    fn metrics_fields_accessible() {
47        let m = StepMetrics {
48            total_us: 100,
49            command_processing_us: 20,
50            propagator_us: vec![("diffusion".to_string(), 50), ("decay".to_string(), 30)],
51            snapshot_publish_us: 10,
52            memory_bytes: 4096,
53            sparse_retired_ranges: 3,
54            sparse_pending_retired: 1,
55        };
56        assert_eq!(m.total_us, 100);
57        assert_eq!(m.command_processing_us, 20);
58        assert_eq!(m.propagator_us.len(), 2);
59        assert_eq!(m.propagator_us[0].0, "diffusion");
60        assert_eq!(m.propagator_us[0].1, 50);
61        assert_eq!(m.snapshot_publish_us, 10);
62        assert_eq!(m.memory_bytes, 4096);
63        assert_eq!(m.sparse_retired_ranges, 3);
64        assert_eq!(m.sparse_pending_retired, 1);
65    }
66}