Skip to main content

byteflow/scheduler/
metrics.rs

1use std::sync::atomic::{AtomicU64, Ordering};
2
3/// Runtime-wide counters (design notes §26). Every field is a plain
4/// `AtomicU64` bumped with `Relaxed` ordering: these are monitoring
5/// counters, not synchronization primitives, so we don't pay for anything
6/// stronger than "eventually visible to a metrics scrape."
7#[derive(Default)]
8pub struct RuntimeMetrics {
9    pub processes_spawned: AtomicU64,
10    pub processes_completed: AtomicU64,
11    pub processes_failed: AtomicU64,
12    pub messages_sent: AtomicU64,
13    pub steals: AtomicU64,
14    pub reschedules: AtomicU64,
15    #[cfg(feature = "jit")]
16    pub jit_compiles: AtomicU64,
17    #[cfg(feature = "jit")]
18    pub jit_compile_failures: AtomicU64,
19    #[cfg(feature = "jit")]
20    pub jit_executions: AtomicU64,
21    #[cfg(feature = "jit")]
22    pub jit_misses: AtomicU64,
23    #[cfg(feature = "jit")]
24    pub jit_deopts: AtomicU64,
25}
26
27impl RuntimeMetrics {
28    #[inline]
29    pub fn inc(counter: &AtomicU64) {
30        counter.fetch_add(1, Ordering::Relaxed);
31    }
32
33    pub fn snapshot(&self) -> RuntimeMetricsSnapshot {
34        RuntimeMetricsSnapshot {
35            processes_spawned: self.processes_spawned.load(Ordering::Relaxed),
36            processes_completed: self.processes_completed.load(Ordering::Relaxed),
37            processes_failed: self.processes_failed.load(Ordering::Relaxed),
38            messages_sent: self.messages_sent.load(Ordering::Relaxed),
39            steals: self.steals.load(Ordering::Relaxed),
40            reschedules: self.reschedules.load(Ordering::Relaxed),
41            #[cfg(feature = "jit")]
42            jit_compiles: self.jit_compiles.load(Ordering::Relaxed),
43            #[cfg(feature = "jit")]
44            jit_compile_failures: self.jit_compile_failures.load(Ordering::Relaxed),
45            #[cfg(feature = "jit")]
46            jit_executions: self.jit_executions.load(Ordering::Relaxed),
47            #[cfg(feature = "jit")]
48            jit_misses: self.jit_misses.load(Ordering::Relaxed),
49            #[cfg(feature = "jit")]
50            jit_deopts: self.jit_deopts.load(Ordering::Relaxed),
51        }
52    }
53}
54
55/// Point-in-time, non-atomic copy of [`RuntimeMetrics`] suitable for
56/// printing or exporting.
57#[derive(Debug, Clone, Copy, Default)]
58pub struct RuntimeMetricsSnapshot {
59    pub processes_spawned: u64,
60    pub processes_completed: u64,
61    pub processes_failed: u64,
62    pub messages_sent: u64,
63    pub steals: u64,
64    pub reschedules: u64,
65    #[cfg(feature = "jit")]
66    pub jit_compiles: u64,
67    #[cfg(feature = "jit")]
68    pub jit_compile_failures: u64,
69    #[cfg(feature = "jit")]
70    pub jit_executions: u64,
71    #[cfg(feature = "jit")]
72    pub jit_misses: u64,
73    #[cfg(feature = "jit")]
74    pub jit_deopts: u64,
75}
76
77impl std::fmt::Display for RuntimeMetricsSnapshot {
78    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79        write!(
80            f,
81            "spawned={} completed={} failed={} messages={} steals={} reschedules={}",
82            self.processes_spawned,
83            self.processes_completed,
84            self.processes_failed,
85            self.messages_sent,
86            self.steals,
87            self.reschedules,
88        )?;
89        #[cfg(feature = "jit")]
90        write!(
91            f,
92            " jit_compiles={} jit_failures={} jit_exec={} jit_miss={} jit_deopt={}",
93            self.jit_compiles,
94            self.jit_compile_failures,
95            self.jit_executions,
96            self.jit_misses,
97            self.jit_deopts,
98        )?;
99        Ok(())
100    }
101}