cache_rs/metrics/
slru.rs

1//! SLRU Cache Metrics
2//!
3//! Metrics specific to the SLRU (Segmented Least Recently Used) cache algorithm.
4
5extern crate alloc;
6
7use super::{CacheMetrics, CoreCacheMetrics};
8use alloc::collections::BTreeMap;
9use alloc::string::{String, ToString};
10
11/// SLRU-specific metrics (extends CoreCacheMetrics)
12///
13/// This struct contains metrics specific to the SLRU (Segmented LRU) cache algorithm.
14/// SLRU divides the cache into probationary and protected segments, so these metrics
15/// focus on segment utilization and promotion/demotion patterns.
16#[derive(Debug, Clone)]
17pub struct SlruCacheMetrics {
18    /// Core metrics common to all cache algorithms
19    pub core: CoreCacheMetrics,
20
21    /// Number of items currently in the probationary segment
22    pub probationary_size: u64,
23
24    /// Number of items currently in the protected segment
25    pub protected_size: u64,
26
27    /// Maximum allowed size for the protected segment
28    pub protected_max_size: u64,
29
30    /// Total number of promotions from probationary to protected segment
31    pub total_promotions: u64,
32
33    /// Total number of demotions from protected to probationary segment
34    pub total_demotions: u64,
35
36    /// Number of cache hits in the probationary segment
37    pub probationary_hits: u64,
38
39    /// Number of cache hits in the protected segment
40    pub protected_hits: u64,
41
42    /// Number of evictions from the probationary segment
43    pub probationary_evictions: u64,
44
45    /// Number of evictions from the protected segment
46    pub protected_evictions: u64,
47}
48
49impl SlruCacheMetrics {
50    /// Creates a new SlruCacheMetrics instance with the specified parameters
51    ///
52    /// # Arguments
53    /// * `max_cache_size_bytes` - The maximum allowed cache size in bytes
54    /// * `protected_max_size` - The maximum number of items in protected segment
55    pub fn new(max_cache_size_bytes: u64, protected_max_size: u64) -> Self {
56        Self {
57            core: CoreCacheMetrics::new(max_cache_size_bytes),
58            probationary_size: 0,
59            protected_size: 0,
60            protected_max_size,
61            total_promotions: 0,
62            total_demotions: 0,
63            probationary_hits: 0,
64            protected_hits: 0,
65            probationary_evictions: 0,
66            protected_evictions: 0,
67        }
68    }
69
70    /// Records a promotion from probationary to protected segment
71    pub fn record_promotion(&mut self) {
72        self.total_promotions += 1;
73    }
74
75    /// Records a demotion from protected to probationary segment
76    pub fn record_demotion(&mut self) {
77        self.total_demotions += 1;
78    }
79
80    /// Records a cache hit in the probationary segment
81    ///
82    /// # Arguments
83    /// * `object_size` - Size of the object that was served from cache (in bytes)
84    pub fn record_probationary_hit(&mut self, object_size: u64) {
85        self.core.record_hit(object_size);
86        self.probationary_hits += 1;
87    }
88
89    /// Records a cache hit in the protected segment
90    ///
91    /// # Arguments
92    /// * `object_size` - Size of the object that was served from cache (in bytes)
93    pub fn record_protected_hit(&mut self, object_size: u64) {
94        self.core.record_hit(object_size);
95        self.protected_hits += 1;
96    }
97
98    /// Records an eviction from the probationary segment
99    ///
100    /// # Arguments
101    /// * `evicted_size` - Size of the evicted object (in bytes)
102    pub fn record_probationary_eviction(&mut self, evicted_size: u64) {
103        self.core.record_eviction(evicted_size);
104        self.probationary_evictions += 1;
105    }
106
107    /// Records an eviction from the protected segment
108    ///
109    /// # Arguments
110    /// * `evicted_size` - Size of the evicted object (in bytes)
111    pub fn record_protected_eviction(&mut self, evicted_size: u64) {
112        self.core.record_eviction(evicted_size);
113        self.protected_evictions += 1;
114    }
115
116    /// Updates the segment sizes
117    ///
118    /// # Arguments
119    /// * `probationary_size` - Current number of items in probationary segment
120    /// * `protected_size` - Current number of items in protected segment
121    pub fn update_segment_sizes(&mut self, probationary_size: u64, protected_size: u64) {
122        self.probationary_size = probationary_size;
123        self.protected_size = protected_size;
124    }
125
126    /// Calculates the protection ratio (protected hits / total hits)
127    ///
128    /// # Returns
129    /// Ratio of hits in protected segment vs total hits, or 0.0 if no hits
130    pub fn protection_ratio(&self) -> f64 {
131        if self.core.cache_hits > 0 {
132            self.protected_hits as f64 / self.core.cache_hits as f64
133        } else {
134            0.0
135        }
136    }
137
138    /// Calculates the promotion efficiency (promotions / probationary hits)
139    ///
140    /// # Returns
141    /// How often probationary hits lead to promotions, or 0.0 if no probationary hits
142    pub fn promotion_efficiency(&self) -> f64 {
143        if self.probationary_hits > 0 {
144            self.total_promotions as f64 / self.probationary_hits as f64
145        } else {
146            0.0
147        }
148    }
149
150    /// Calculates protected segment utilization
151    ///
152    /// # Returns
153    /// Ratio of current protected size to maximum protected size
154    pub fn protected_utilization(&self) -> f64 {
155        if self.protected_max_size > 0 {
156            self.protected_size as f64 / self.protected_max_size as f64
157        } else {
158            0.0
159        }
160    }
161
162    /// Converts SLRU metrics to a BTreeMap for reporting
163    ///
164    /// This method returns all metrics relevant to the SLRU cache algorithm,
165    /// including both core metrics and SLRU-specific segment metrics.
166    ///
167    /// Uses BTreeMap to ensure consistent, deterministic ordering of metrics.
168    ///
169    /// # Returns
170    /// A BTreeMap containing all SLRU cache metrics as key-value pairs
171    pub fn to_btreemap(&self) -> BTreeMap<String, f64> {
172        let mut metrics = self.core.to_btreemap();
173
174        // SLRU-specific segment metrics
175        metrics.insert(
176            "probationary_size".to_string(),
177            self.probationary_size as f64,
178        );
179        metrics.insert("protected_size".to_string(), self.protected_size as f64);
180        metrics.insert(
181            "protected_max_size".to_string(),
182            self.protected_max_size as f64,
183        );
184        metrics.insert(
185            "protected_utilization".to_string(),
186            self.protected_utilization(),
187        );
188
189        // Movement metrics
190        metrics.insert("total_promotions".to_string(), self.total_promotions as f64);
191        metrics.insert("total_demotions".to_string(), self.total_demotions as f64);
192
193        // Segment-specific hit metrics
194        metrics.insert(
195            "probationary_hits".to_string(),
196            self.probationary_hits as f64,
197        );
198        metrics.insert("protected_hits".to_string(), self.protected_hits as f64);
199        metrics.insert("protection_ratio".to_string(), self.protection_ratio());
200
201        // Segment-specific eviction metrics
202        metrics.insert(
203            "probationary_evictions".to_string(),
204            self.probationary_evictions as f64,
205        );
206        metrics.insert(
207            "protected_evictions".to_string(),
208            self.protected_evictions as f64,
209        );
210
211        // Efficiency metrics
212        metrics.insert(
213            "promotion_efficiency".to_string(),
214            self.promotion_efficiency(),
215        );
216
217        if self.core.requests > 0 {
218            metrics.insert(
219                "promotion_rate".to_string(),
220                self.total_promotions as f64 / self.core.requests as f64,
221            );
222            metrics.insert(
223                "demotion_rate".to_string(),
224                self.total_demotions as f64 / self.core.requests as f64,
225            );
226        }
227
228        metrics
229    }
230}
231
232impl CacheMetrics for SlruCacheMetrics {
233    /// Returns all SLRU cache metrics as key-value pairs in deterministic order
234    ///
235    /// # Returns
236    /// A BTreeMap containing all metrics tracked by this SLRU cache instance
237    fn metrics(&self) -> BTreeMap<String, f64> {
238        self.to_btreemap()
239    }
240
241    /// Returns the algorithm name for this cache implementation
242    ///
243    /// # Returns
244    /// "SLRU" - identifying this as a Segmented Least Recently Used cache
245    fn algorithm_name(&self) -> &'static str {
246        "SLRU"
247    }
248}