extern crate alloc;
use super::{CacheMetrics, CoreCacheMetrics};
use alloc::collections::BTreeMap;
use alloc::string::{String, ToString};
#[derive(Debug, Clone)]
pub struct LfuCacheMetrics {
pub core: CoreCacheMetrics,
pub min_frequency: u64,
pub max_frequency: u64,
pub total_frequency_increments: u64,
pub active_frequency_levels: u64,
}
impl LfuCacheMetrics {
pub fn new(max_cache_size_bytes: u64) -> Self {
Self {
core: CoreCacheMetrics::new(max_cache_size_bytes),
min_frequency: 0,
max_frequency: 0,
total_frequency_increments: 0,
active_frequency_levels: 0,
}
}
pub fn record_frequency_increment(&mut self, _old_frequency: usize, new_frequency: usize) {
self.total_frequency_increments += 1;
let new_freq_u64 = new_frequency as u64;
if self.min_frequency == 0 || new_freq_u64 < self.min_frequency {
self.min_frequency = new_freq_u64;
}
if new_freq_u64 > self.max_frequency {
self.max_frequency = new_freq_u64;
}
}
pub fn record_frequency_hit(&mut self, object_size: u64, frequency: usize) {
self.core.record_hit(object_size);
let freq_u64 = frequency as u64;
if self.min_frequency == 0 || freq_u64 < self.min_frequency {
self.min_frequency = freq_u64;
}
if freq_u64 > self.max_frequency {
self.max_frequency = freq_u64;
}
}
pub fn update_frequency_levels<T>(&mut self, frequency_lists: &BTreeMap<usize, T>) {
self.active_frequency_levels = frequency_lists.len() as u64;
if let (Some(&min_freq), Some(&max_freq)) =
(frequency_lists.keys().min(), frequency_lists.keys().max())
{
self.min_frequency = min_freq as u64;
self.max_frequency = max_freq as u64;
}
}
pub fn record_miss(&mut self, object_size: u64) {
self.core.record_miss(object_size);
}
pub fn update_active_frequency_levels(&mut self, levels: u64) {
self.active_frequency_levels = levels;
}
pub fn average_frequency(&self) -> f64 {
if self.core.cache_hits > 0 {
self.total_frequency_increments as f64 / self.core.cache_hits as f64
} else {
0.0
}
}
pub fn frequency_range(&self) -> u64 {
self.max_frequency.saturating_sub(self.min_frequency)
}
pub fn to_btreemap(&self) -> BTreeMap<String, f64> {
let mut metrics = self.core.to_btreemap();
metrics.insert("min_frequency".to_string(), self.min_frequency as f64);
metrics.insert("max_frequency".to_string(), self.max_frequency as f64);
metrics.insert("frequency_range".to_string(), self.frequency_range() as f64);
metrics.insert(
"total_frequency_increments".to_string(),
self.total_frequency_increments as f64,
);
metrics.insert(
"active_frequency_levels".to_string(),
self.active_frequency_levels as f64,
);
metrics.insert("average_frequency".to_string(), self.average_frequency());
if self.core.requests > 0 {
metrics.insert(
"frequency_increment_rate".to_string(),
self.total_frequency_increments as f64 / self.core.requests as f64,
);
}
if self.active_frequency_levels > 0 && self.core.cache_hits > 0 {
metrics.insert(
"frequency_distribution_efficiency".to_string(),
self.active_frequency_levels as f64 / self.core.cache_hits as f64,
);
}
metrics
}
}
impl CacheMetrics for LfuCacheMetrics {
fn metrics(&self) -> BTreeMap<String, f64> {
self.to_btreemap()
}
fn algorithm_name(&self) -> &'static str {
"LFU"
}
}