Skip to main content

nodedb_mem/
pressure.rs

1// SPDX-License-Identifier: BUSL-1.1
2
3//! Memory pressure levels for gradual backpressure.
4//!
5//! Instead of binary accept/reject, the governor reports pressure levels
6//! so callers can take graduated action:
7//!
8//! - **Normal**: full speed, no restrictions.
9//! - **Warning**: start spilling large allocations to disk, reduce batch sizes.
10//! - **Critical**: reject new allocations, force spill of in-progress work.
11//!
12//! Pressure is computed per-engine and globally.
13
14/// Memory pressure level.
15#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
16pub enum PressureLevel {
17    /// Below 70% utilization. No restrictions.
18    Normal,
19    /// 70-85% utilization. Caller should prefer smaller allocations,
20    /// start spilling large temporary buffers to disk.
21    Warning,
22    /// 85-95% utilization. Caller must spill or backpressure.
23    /// New large allocations should be rejected.
24    Critical,
25    /// Over 95% utilization. Emergency: only essential allocations permitted.
26    /// All non-essential work must stop.
27    Emergency,
28}
29
30/// Thresholds for pressure level transitions (percentage of budget).
31#[derive(Debug, Clone, Copy)]
32pub struct PressureThresholds {
33    /// Enter Warning at this utilization (default: 70%).
34    pub warning: u8,
35    /// Enter Critical at this utilization (default: 85%).
36    pub critical: u8,
37    /// Enter Emergency at this utilization (default: 95%).
38    pub emergency: u8,
39}
40
41impl Default for PressureThresholds {
42    fn default() -> Self {
43        Self {
44            warning: 70,
45            critical: 85,
46            emergency: 95,
47        }
48    }
49}
50
51impl PressureThresholds {
52    /// Compute the pressure level for a given utilization percentage.
53    pub fn level_for(&self, utilization_percent: u8) -> PressureLevel {
54        if utilization_percent >= self.emergency {
55            PressureLevel::Emergency
56        } else if utilization_percent >= self.critical {
57            PressureLevel::Critical
58        } else if utilization_percent >= self.warning {
59            PressureLevel::Warning
60        } else {
61            PressureLevel::Normal
62        }
63    }
64}
65
66#[cfg(test)]
67mod tests {
68    use super::*;
69
70    #[test]
71    fn default_thresholds() {
72        let t = PressureThresholds::default();
73        assert_eq!(t.level_for(0), PressureLevel::Normal);
74        assert_eq!(t.level_for(69), PressureLevel::Normal);
75        assert_eq!(t.level_for(70), PressureLevel::Warning);
76        assert_eq!(t.level_for(84), PressureLevel::Warning);
77        assert_eq!(t.level_for(85), PressureLevel::Critical);
78        assert_eq!(t.level_for(94), PressureLevel::Critical);
79        assert_eq!(t.level_for(95), PressureLevel::Emergency);
80        assert_eq!(t.level_for(100), PressureLevel::Emergency);
81    }
82
83    #[test]
84    fn pressure_ordering() {
85        assert!(PressureLevel::Normal < PressureLevel::Warning);
86        assert!(PressureLevel::Warning < PressureLevel::Critical);
87        assert!(PressureLevel::Critical < PressureLevel::Emergency);
88    }
89}