Skip to main content

revmc_runtime/runtime/
stats.rs

1//! Runtime statistics.
2
3use std::sync::atomic::{AtomicU64, Ordering};
4
5/// Atomic counters for runtime observability.
6#[derive(Debug, Default)]
7pub(crate) struct RuntimeStats {
8    /// Total lookups that returned a compiled function.
9    pub(crate) lookup_hits: AtomicU64,
10    /// Total lookups that returned interpret (not ready).
11    pub(crate) lookup_misses: AtomicU64,
12    /// Total lookup events dropped due to event-queue overflow.
13    pub(crate) events_dropped: AtomicU64,
14    /// Total control commands dropped because the command channel was full.
15    pub(crate) commands_dropped: AtomicU64,
16    /// Total number of entries evicted (idle + budget).
17    pub(crate) evictions: AtomicU64,
18    /// Total number of compilations dispatched (JIT promotions + AOT requests).
19    pub(crate) compilations_dispatched: AtomicU64,
20    /// Total number of successful compilations (JIT + AOT).
21    pub(crate) compilations_succeeded: AtomicU64,
22    /// Total number of failed compilations (JIT + AOT).
23    pub(crate) compilations_failed: AtomicU64,
24    /// Total number of out-of-process JIT helper processes spawned successfully.
25    pub(crate) jit_helper_spawns: AtomicU64,
26    /// Total number of failed out-of-process JIT helper spawn attempts.
27    pub(crate) jit_helper_spawn_failures: AtomicU64,
28    /// Total number of out-of-process JIT helpers discarded for restart.
29    pub(crate) jit_helper_restarts: AtomicU64,
30    /// Total number of out-of-process JIT helper job timeouts.
31    pub(crate) jit_helper_timeouts: AtomicU64,
32    /// Total number of out-of-process JIT helper disconnects.
33    pub(crate) jit_helper_disconnects: AtomicU64,
34    /// Total number of out-of-process JIT helper pause requests.
35    pub(crate) jit_helper_pause_requests: AtomicU64,
36    /// Total number of graceful out-of-process JIT helper pause acknowledgements.
37    pub(crate) jit_helper_pause_acknowledgements: AtomicU64,
38    /// Total number of graceful out-of-process JIT helper pause failures.
39    pub(crate) jit_helper_pause_failures: AtomicU64,
40    /// Total number of graceful out-of-process JIT helper pause acknowledgement timeouts.
41    pub(crate) jit_helper_pause_timeouts: AtomicU64,
42    /// Total number of out-of-process JIT helper resume requests.
43    pub(crate) jit_helper_resume_requests: AtomicU64,
44    /// Total number of out-of-process JIT helper resume request failures.
45    pub(crate) jit_helper_resume_failures: AtomicU64,
46}
47
48/// Gauge values sampled at snapshot time.
49#[derive(Clone, Copy, Debug, Default)]
50pub(crate) struct RuntimeStatsGauges {
51    pub(crate) resident_entries: u64,
52    pub(crate) events_queued: u64,
53    pub(crate) command_queue_len: u64,
54}
55
56/// A point-in-time snapshot of runtime stats.
57#[derive(Clone, Copy, Debug, Default)]
58pub struct RuntimeStatsSnapshot {
59    /// Total lookups that returned a compiled function.
60    pub lookup_hits: u64,
61    /// Total lookups that returned interpret (not ready).
62    pub lookup_misses: u64,
63    /// Total lookup events dropped due to event-queue overflow.
64    pub events_dropped: u64,
65    /// Total control commands dropped because the command channel was full.
66    ///
67    /// Pause/resume commands are best-effort and dropped instead of blocking the caller when
68    /// the command channel is full.
69    pub commands_dropped: u64,
70    /// Number of entries in the resident compiled map.
71    pub resident_entries: u64,
72    /// Number of lookup events currently queued for the backend.
73    pub events_queued: u64,
74    /// Number of pending control commands queued for the backend.
75    pub command_queue_len: u64,
76    /// Number of compilation jobs currently in flight (dispatched but not yet completed).
77    pub pending_jobs: u64,
78    /// Bytes allocated for executable JIT code sections.
79    ///
80    /// Sourced from the LLVM JIT memory usage plugin. Reflects live memory:
81    /// bytes are added on compilation and subtracted when JIT code is freed.
82    /// `0` if the LLVM backend is not initialized.
83    pub jit_code_bytes: u64,
84    /// Bytes allocated for non-executable JIT data sections.
85    ///
86    /// Sourced from the LLVM JIT memory usage plugin. `0` if not initialized.
87    pub jit_data_bytes: u64,
88    /// Total number of entries evicted (idle + budget).
89    pub evictions: u64,
90    /// Total number of compilations dispatched (JIT promotions + AOT requests).
91    pub compilations_dispatched: u64,
92    /// Total number of successful compilations (JIT + AOT).
93    pub compilations_succeeded: u64,
94    /// Total number of failed compilations (JIT + AOT).
95    pub compilations_failed: u64,
96    /// Total number of out-of-process JIT helper processes spawned successfully.
97    pub jit_helper_spawns: u64,
98    /// Total number of failed out-of-process JIT helper spawn attempts.
99    pub jit_helper_spawn_failures: u64,
100    /// Total number of out-of-process JIT helpers discarded for restart.
101    pub jit_helper_restarts: u64,
102    /// Total number of out-of-process JIT helper job timeouts.
103    pub jit_helper_timeouts: u64,
104    /// Total number of out-of-process JIT helper disconnects.
105    pub jit_helper_disconnects: u64,
106    /// Total number of out-of-process JIT helper pause requests.
107    pub jit_helper_pause_requests: u64,
108    /// Total number of graceful out-of-process JIT helper pause acknowledgements.
109    pub jit_helper_pause_acknowledgements: u64,
110    /// Total number of graceful out-of-process JIT helper pause failures.
111    pub jit_helper_pause_failures: u64,
112    /// Total number of graceful out-of-process JIT helper pause acknowledgement timeouts.
113    pub jit_helper_pause_timeouts: u64,
114    /// Total number of out-of-process JIT helper resume requests.
115    pub jit_helper_resume_requests: u64,
116    /// Total number of out-of-process JIT helper resume request failures.
117    pub jit_helper_resume_failures: u64,
118}
119
120impl RuntimeStatsSnapshot {
121    /// Total bytes allocated by the JIT engine (code + data).
122    pub fn jit_total_bytes(&self) -> u64 {
123        self.jit_code_bytes + self.jit_data_bytes
124    }
125}
126
127impl RuntimeStats {
128    pub(crate) fn snapshot(&self, gauges: RuntimeStatsGauges) -> RuntimeStatsSnapshot {
129        #[cfg(feature = "llvm")]
130        let (jit_code_bytes, jit_data_bytes) = crate::llvm::jit_memory_usage()
131            .map(|u| (u.code_bytes as u64, u.data_bytes as u64))
132            .unwrap_or((0, 0));
133        #[cfg(not(feature = "llvm"))]
134        let (jit_code_bytes, jit_data_bytes) = (0, 0);
135
136        let dispatched = self.compilations_dispatched.load(Ordering::Relaxed);
137        let succeeded = self.compilations_succeeded.load(Ordering::Relaxed);
138        let failed = self.compilations_failed.load(Ordering::Relaxed);
139        let pending_jobs = dispatched.saturating_sub(succeeded.saturating_add(failed));
140
141        RuntimeStatsSnapshot {
142            lookup_hits: self.lookup_hits.load(Ordering::Relaxed),
143            lookup_misses: self.lookup_misses.load(Ordering::Relaxed),
144            events_dropped: self.events_dropped.load(Ordering::Relaxed),
145            commands_dropped: self.commands_dropped.load(Ordering::Relaxed),
146            resident_entries: gauges.resident_entries,
147            events_queued: gauges.events_queued,
148            command_queue_len: gauges.command_queue_len,
149            pending_jobs,
150            jit_code_bytes,
151            jit_data_bytes,
152            evictions: self.evictions.load(Ordering::Relaxed),
153            compilations_dispatched: dispatched,
154            compilations_succeeded: succeeded,
155            compilations_failed: failed,
156            jit_helper_spawns: self.jit_helper_spawns.load(Ordering::Relaxed),
157            jit_helper_spawn_failures: self.jit_helper_spawn_failures.load(Ordering::Relaxed),
158            jit_helper_restarts: self.jit_helper_restarts.load(Ordering::Relaxed),
159            jit_helper_timeouts: self.jit_helper_timeouts.load(Ordering::Relaxed),
160            jit_helper_disconnects: self.jit_helper_disconnects.load(Ordering::Relaxed),
161            jit_helper_pause_requests: self.jit_helper_pause_requests.load(Ordering::Relaxed),
162            jit_helper_pause_acknowledgements: self
163                .jit_helper_pause_acknowledgements
164                .load(Ordering::Relaxed),
165            jit_helper_pause_failures: self.jit_helper_pause_failures.load(Ordering::Relaxed),
166            jit_helper_pause_timeouts: self.jit_helper_pause_timeouts.load(Ordering::Relaxed),
167            jit_helper_resume_requests: self.jit_helper_resume_requests.load(Ordering::Relaxed),
168            jit_helper_resume_failures: self.jit_helper_resume_failures.load(Ordering::Relaxed),
169        }
170    }
171}