Skip to main content

nodedb_mem/
pressure.rs

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