#[derive(Clone, Copy, Debug)]
pub struct WTinyLFUConfig {
pub window_ratio: f64,
pub sketch_width: usize,
pub sketch_depth: usize,
pub decay_interval: u64,
}
impl WTinyLFUConfig {
pub fn new(
window_ratio: f64,
sketch_width: usize,
sketch_depth: usize,
decay_interval: u64,
) -> Self {
Self {
window_ratio: window_ratio.clamp(0.01, 0.99),
sketch_width,
sketch_depth,
decay_interval,
}
}
pub fn window_size(&self, total_capacity: usize) -> usize {
((total_capacity as f64 * self.window_ratio).round() as usize).max(1)
}
pub fn protected_size(&self, total_capacity: usize) -> usize {
total_capacity.saturating_sub(self.window_size(total_capacity))
}
}
impl Default for WTinyLFUConfig {
fn default() -> Self {
Self {
window_ratio: 0.20,
sketch_width: 2048,
sketch_depth: 4,
decay_interval: 10000,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = WTinyLFUConfig::default();
assert_eq!(config.window_ratio, 0.20);
assert_eq!(config.sketch_width, 2048);
assert_eq!(config.sketch_depth, 4);
assert_eq!(config.decay_interval, 10000);
}
#[test]
fn test_custom_config() {
let config = WTinyLFUConfig::new(0.15, 4096, 8, 20000);
assert_eq!(config.window_ratio, 0.15);
assert_eq!(config.sketch_width, 4096);
assert_eq!(config.sketch_depth, 8);
assert_eq!(config.decay_interval, 20000);
}
#[test]
fn test_window_ratio_clamping() {
let too_low = WTinyLFUConfig::new(0.0, 2048, 4, 10000);
assert_eq!(too_low.window_ratio, 0.01);
let too_high = WTinyLFUConfig::new(1.5, 2048, 4, 10000);
assert_eq!(too_high.window_ratio, 0.99);
}
#[test]
fn test_window_size_calculation() {
let config = WTinyLFUConfig::default();
assert_eq!(config.window_size(100), 20);
assert_eq!(config.window_size(50), 10);
assert_eq!(config.window_size(10), 2);
assert_eq!(config.window_size(5), 1); assert_eq!(config.window_size(1), 1);
}
#[test]
fn test_protected_size_calculation() {
let config = WTinyLFUConfig::default();
assert_eq!(config.protected_size(100), 80);
assert_eq!(config.protected_size(50), 40);
assert_eq!(config.protected_size(10), 8);
assert_eq!(config.protected_size(5), 4);
}
#[test]
fn test_custom_window_ratio() {
let config = WTinyLFUConfig::new(0.10, 2048, 4, 10000);
assert_eq!(config.window_size(100), 10);
assert_eq!(config.protected_size(100), 90);
let large_window = WTinyLFUConfig::new(0.50, 2048, 4, 10000); assert_eq!(large_window.window_size(100), 50);
assert_eq!(large_window.protected_size(100), 50);
}
#[test]
fn test_total_equals_capacity() {
let config = WTinyLFUConfig::default();
for capacity in [10, 50, 100, 1000, 10000] {
let window = config.window_size(capacity);
let protected = config.protected_size(capacity);
assert_eq!(window + protected, capacity);
}
}
}