extern crate alloc;
use alloc::collections::BTreeMap;
use alloc::string::{String, ToString};
pub mod gdsf;
pub mod lfu;
pub mod lfuda;
pub mod lru;
pub mod slru;
pub use gdsf::GdsfCacheMetrics;
pub use lfu::LfuCacheMetrics;
pub use lfuda::LfudaCacheMetrics;
pub use lru::LruCacheMetrics;
pub use slru::SlruCacheMetrics;
#[derive(Debug, Default, Clone)]
pub struct CoreCacheMetrics {
pub requests: u64,
pub cache_hits: u64,
pub total_bytes_requested: u64,
pub bytes_served_from_cache: u64,
pub bytes_written_to_cache: u64,
pub evictions: u64,
pub cache_size_bytes: u64,
pub max_cache_size_bytes: u64,
}
impl CoreCacheMetrics {
pub fn new(max_cache_size_bytes: u64) -> Self {
Self {
max_cache_size_bytes,
..Default::default()
}
}
pub fn record_hit(&mut self, object_size: u64) {
self.requests += 1;
self.cache_hits += 1;
self.total_bytes_requested += object_size;
self.bytes_served_from_cache += object_size;
}
pub fn record_miss(&mut self, object_size: u64) {
self.requests += 1;
self.total_bytes_requested += object_size;
}
pub fn record_eviction(&mut self, evicted_size: u64) {
self.evictions += 1;
self.cache_size_bytes = self.cache_size_bytes.saturating_sub(evicted_size);
}
pub fn record_removal(&mut self, removed_size: u64) {
self.cache_size_bytes = self.cache_size_bytes.saturating_sub(removed_size);
}
pub fn record_insertion(&mut self, object_size: u64) {
self.cache_size_bytes += object_size;
self.bytes_written_to_cache += object_size;
}
pub fn record_size_change(&mut self, old_size: u64, new_size: u64) {
self.cache_size_bytes = self.cache_size_bytes - old_size + new_size;
}
pub fn hit_rate(&self) -> f64 {
if self.requests > 0 {
self.cache_hits as f64 / self.requests as f64
} else {
0.0
}
}
pub fn miss_rate(&self) -> f64 {
if self.requests > 0 {
(self.requests - self.cache_hits) as f64 / self.requests as f64
} else {
0.0
}
}
pub fn byte_hit_rate(&self) -> f64 {
if self.total_bytes_requested > 0 {
self.bytes_served_from_cache as f64 / self.total_bytes_requested as f64
} else {
0.0
}
}
pub fn cache_utilization(&self) -> f64 {
if self.max_cache_size_bytes > 0 {
self.cache_size_bytes as f64 / self.max_cache_size_bytes as f64
} else {
0.0
}
}
pub fn to_btreemap(&self) -> BTreeMap<String, f64> {
let mut metrics = BTreeMap::new();
metrics.insert("cache_hits".to_string(), self.cache_hits as f64);
metrics.insert("evictions".to_string(), self.evictions as f64);
metrics.insert("requests".to_string(), self.requests as f64);
metrics.insert(
"cache_misses".to_string(),
(self.requests - self.cache_hits) as f64,
);
metrics.insert("hit_rate".to_string(), self.hit_rate());
metrics.insert("miss_rate".to_string(), self.miss_rate());
metrics.insert("byte_hit_rate".to_string(), self.byte_hit_rate());
metrics.insert(
"bytes_served_from_cache".to_string(),
self.bytes_served_from_cache as f64,
);
metrics.insert(
"bytes_written_to_cache".to_string(),
self.bytes_written_to_cache as f64,
);
metrics.insert(
"total_bytes_requested".to_string(),
self.total_bytes_requested as f64,
);
metrics.insert("cache_size_bytes".to_string(), self.cache_size_bytes as f64);
metrics.insert(
"max_cache_size_bytes".to_string(),
self.max_cache_size_bytes as f64,
);
metrics.insert("cache_utilization".to_string(), self.cache_utilization());
if self.requests > 0 {
metrics.insert(
"avg_object_size".to_string(),
self.total_bytes_requested as f64 / self.requests as f64,
);
metrics.insert(
"eviction_rate".to_string(),
self.evictions as f64 / self.requests as f64,
);
}
metrics
}
}
pub trait CacheMetrics {
fn metrics(&self) -> BTreeMap<String, f64>;
fn algorithm_name(&self) -> &'static str;
}