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 => {
55                vtcode_config::constants::memory::WARNING_TTL_REDUCTION_FACTOR
56            }
57            MemoryPressure::Critical => {
58                vtcode_config::constants::memory::CRITICAL_TTL_REDUCTION_FACTOR
59            }
60        }
61    }
62}
63
64impl fmt::Display for MemoryPressure {
65    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66        match self {
67            MemoryPressure::Normal => write!(f, "Normal"),
68            MemoryPressure::Warning => write!(f, "Warning"),
69            MemoryPressure::Critical => write!(f, "Critical"),
70        }
71    }
72}
73
74#[cfg(test)]
75mod tests {
76    use super::*;
77
78    #[test]
79    fn test_memory_pressure_from_rss_normal() {
80        let soft_limit = vtcode_config::constants::memory::SOFT_LIMIT_BYTES;
81        let pressure = MemoryPressure::from_rss(soft_limit - 1024); // Just under soft limit
82        assert_eq!(pressure, MemoryPressure::Normal);
83    }
84
85    #[test]
86    fn test_memory_pressure_from_rss_warning() {
87        let soft_limit = vtcode_config::constants::memory::SOFT_LIMIT_BYTES;
88        let hard_limit = vtcode_config::constants::memory::HARD_LIMIT_BYTES;
89        let mid_point = (soft_limit + hard_limit) / 2;
90        let pressure = MemoryPressure::from_rss(mid_point);
91        assert_eq!(pressure, MemoryPressure::Warning);
92    }
93
94    #[test]
95    fn test_memory_pressure_from_rss_critical() {
96        let hard_limit = vtcode_config::constants::memory::HARD_LIMIT_BYTES;
97        let pressure = MemoryPressure::from_rss(hard_limit + 1024); // Just over hard limit
98        assert_eq!(pressure, MemoryPressure::Critical);
99    }
100
101    #[test]
102    fn test_should_evict() {
103        assert!(!MemoryPressure::Normal.should_evict());
104        assert!(MemoryPressure::Warning.should_evict());
105        assert!(MemoryPressure::Critical.should_evict());
106    }
107
108    #[test]
109    fn test_should_evict_aggressively() {
110        assert!(!MemoryPressure::Normal.should_evict_aggressively());
111        assert!(!MemoryPressure::Warning.should_evict_aggressively());
112        assert!(MemoryPressure::Critical.should_evict_aggressively());
113    }
114
115    #[test]
116    fn test_ttl_reduction_factors() {
117        let normal_factor = MemoryPressure::Normal.ttl_reduction_factor();
118        let warning_factor = MemoryPressure::Warning.ttl_reduction_factor();
119        let critical_factor = MemoryPressure::Critical.ttl_reduction_factor();
120
121        // Factors should be in decreasing order
122        assert!(normal_factor > warning_factor);
123        assert!(warning_factor > critical_factor);
124
125        // Values should be between 0 and 1
126        assert!(normal_factor <= 1.0);
127        assert!(critical_factor > 0.0);
128    }
129
130    #[test]
131    fn test_display() {
132        assert_eq!(format!("{}", MemoryPressure::Normal), "Normal");
133        assert_eq!(format!("{}", MemoryPressure::Warning), "Warning");
134        assert_eq!(format!("{}", MemoryPressure::Critical), "Critical");
135    }
136}