Skip to main content

vtcode_core/memory/
pressure.rs

1//! Memory pressure classification system
2
3use std::fmt;
4
5/// Memory pressure levels
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum MemoryPressure {
8    /// Normal memory usage (< 400 MB)
9    Normal,
10    /// Warning level (400-600 MB) - reduce TTL, trigger selective eviction
11    Warning,
12    /// Critical level (>= 600 MB) - aggressive eviction, clear caches
13    Critical,
14}
15
16impl MemoryPressure {
17    /// Classify memory pressure based on RSS bytes
18    pub fn from_rss(rss_bytes: usize) -> Self {
19        let soft_limit = vtcode_config::constants::memory::SOFT_LIMIT_BYTES;
20        let hard_limit = vtcode_config::constants::memory::HARD_LIMIT_BYTES;
21
22        if rss_bytes >= hard_limit {
23            MemoryPressure::Critical
24        } else if rss_bytes >= soft_limit {
25            MemoryPressure::Warning
26        } else {
27            MemoryPressure::Normal
28        }
29    }
30
31    /// Check if eviction should be triggered
32    pub fn should_evict(&self) -> bool {
33        matches!(self, MemoryPressure::Warning | MemoryPressure::Critical)
34    }
35
36    /// Check if aggressive eviction should be triggered
37    pub fn should_evict_aggressively(&self) -> bool {
38        matches!(self, MemoryPressure::Critical)
39    }
40
41    /// Get human-readable description
42    pub fn description(&self) -> &'static str {
43        match self {
44            MemoryPressure::Normal => "Normal (memory usage is healthy)",
45            MemoryPressure::Warning => "Warning (approaching soft limit, consider cleanup)",
46            MemoryPressure::Critical => "Critical (at hard limit, aggressive cleanup recommended)",
47        }
48    }
49
50    /// Get TTL reduction factor for cache management
51    pub fn ttl_reduction_factor(&self) -> f64 {
52        match self {
53            MemoryPressure::Normal => 1.0,
54            MemoryPressure::Warning => vtcode_config::constants::memory::WARNING_TTL_REDUCTION_FACTOR,
55            MemoryPressure::Critical => vtcode_config::constants::memory::CRITICAL_TTL_REDUCTION_FACTOR,
56        }
57    }
58}
59
60impl fmt::Display for MemoryPressure {
61    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62        match self {
63            MemoryPressure::Normal => write!(f, "Normal"),
64            MemoryPressure::Warning => write!(f, "Warning"),
65            MemoryPressure::Critical => write!(f, "Critical"),
66        }
67    }
68}
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73
74    #[test]
75    fn test_memory_pressure_from_rss_normal() {
76        let soft_limit = vtcode_config::constants::memory::SOFT_LIMIT_BYTES;
77        let pressure = MemoryPressure::from_rss(soft_limit - 1024); // Just under soft limit
78        assert_eq!(pressure, MemoryPressure::Normal);
79    }
80
81    #[test]
82    fn test_memory_pressure_from_rss_warning() {
83        let soft_limit = vtcode_config::constants::memory::SOFT_LIMIT_BYTES;
84        let hard_limit = vtcode_config::constants::memory::HARD_LIMIT_BYTES;
85        let mid_point = (soft_limit + hard_limit) / 2;
86        let pressure = MemoryPressure::from_rss(mid_point);
87        assert_eq!(pressure, MemoryPressure::Warning);
88    }
89
90    #[test]
91    fn test_memory_pressure_from_rss_critical() {
92        let hard_limit = vtcode_config::constants::memory::HARD_LIMIT_BYTES;
93        let pressure = MemoryPressure::from_rss(hard_limit + 1024); // Just over hard limit
94        assert_eq!(pressure, MemoryPressure::Critical);
95    }
96
97    #[test]
98    fn test_should_evict() {
99        assert!(!MemoryPressure::Normal.should_evict());
100        assert!(MemoryPressure::Warning.should_evict());
101        assert!(MemoryPressure::Critical.should_evict());
102    }
103
104    #[test]
105    fn test_should_evict_aggressively() {
106        assert!(!MemoryPressure::Normal.should_evict_aggressively());
107        assert!(!MemoryPressure::Warning.should_evict_aggressively());
108        assert!(MemoryPressure::Critical.should_evict_aggressively());
109    }
110
111    #[test]
112    fn test_ttl_reduction_factors() {
113        let normal_factor = MemoryPressure::Normal.ttl_reduction_factor();
114        let warning_factor = MemoryPressure::Warning.ttl_reduction_factor();
115        let critical_factor = MemoryPressure::Critical.ttl_reduction_factor();
116
117        // Factors should be in decreasing order
118        assert!(normal_factor > warning_factor);
119        assert!(warning_factor > critical_factor);
120
121        // Values should be between 0 and 1
122        assert!(normal_factor <= 1.0);
123        assert!(critical_factor > 0.0);
124    }
125
126    #[test]
127    fn test_display() {
128        assert_eq!(format!("{}", MemoryPressure::Normal), "Normal");
129        assert_eq!(format!("{}", MemoryPressure::Warning), "Warning");
130        assert_eq!(format!("{}", MemoryPressure::Critical), "Critical");
131    }
132}