pub struct LfudaCache<K, V, S = DefaultHashBuilder> { /* private fields */ }Expand description
An implementation of a Least Frequently Used with Dynamic Aging (LFUDA) cache.
LFUDA improves upon LFU by adding an aging mechanism that prevents old frequently-used items from blocking new items indefinitely. Each item’s effective priority is calculated as (access_frequency + age_at_insertion), where age_at_insertion is the global age value when the item was first inserted.
When an item is evicted, the global age is set to the evicted item’s effective priority, ensuring that new items start with a competitive priority.
§Examples
use cache_rs::lfuda::LfudaCache;
use cache_rs::config::LfudaCacheConfig;
use core::num::NonZeroUsize;
// Create an LFUDA cache with capacity 3
let config = LfudaCacheConfig {
capacity: NonZeroUsize::new(3).unwrap(),
initial_age: 0,
max_size: u64::MAX,
};
let mut cache = LfudaCache::init(config, None);
// Add some items
cache.put("a", 1, 1);
cache.put("b", 2, 1);
cache.put("c", 3, 1);
// Access "a" multiple times to increase its frequency
assert_eq!(cache.get(&"a"), Some(&1));
assert_eq!(cache.get(&"a"), Some(&1));
// Add more items to trigger aging
cache.put("d", 4, 1); // This will evict an item and increase global age
cache.put("e", 5, 1); // New items benefit from the increased ageImplementations§
Source§impl<K: Hash + Eq, V: Clone, S: BuildHasher> LfudaCache<K, V, S>
impl<K: Hash + Eq, V: Clone, S: BuildHasher> LfudaCache<K, V, S>
Sourcepub fn cap(&self) -> NonZeroUsize
pub fn cap(&self) -> NonZeroUsize
Returns the maximum number of key-value pairs the cache can hold.
Sourcepub fn current_size(&self) -> u64
pub fn current_size(&self) -> u64
Returns the current total size of cached content.
Sourcepub fn global_age(&self) -> u64
pub fn global_age(&self) -> u64
Returns the current global age value.
Sourcepub fn record_miss(&mut self, object_size: u64)
pub fn record_miss(&mut self, object_size: u64)
Records a cache miss for metrics tracking (to be called by simulation system)
Sourcepub fn put(&mut self, key: K, value: V, size: u64) -> Option<Vec<(K, V)>>where
K: Clone,
pub fn put(&mut self, key: K, value: V, size: u64) -> Option<Vec<(K, V)>>where
K: Clone,
Inserts a key-value pair into the cache.
If the key already exists, it is replaced. If at capacity, the item with the lowest effective priority is evicted and the global age is updated to the evicted item’s effective priority.
New items are inserted with a frequency of 1 and age_at_insertion set to the
current global_age.
§Arguments
key- The key to insertvalue- The value to insertsize- Optional size in bytes for size-aware caching. UseSIZE_UNIT(1) for count-based caching.
§Returns
Some(vec)containing evicted entries (not replaced entries)Noneif no entries were evicted (zero allocation)
Sourcepub fn clear(&mut self)
pub fn clear(&mut self)
Clears the cache, removing all key-value pairs. Resets the global age to 0.
Sourcepub fn contains<Q>(&self, key: &Q) -> bool
pub fn contains<Q>(&self, key: &Q) -> bool
Check if key exists without updating its priority or access metadata.
Unlike get(), this method does NOT update the entry’s frequency
or access metadata. Useful for existence checks without affecting
cache eviction order.
§Example
use cache_rs::lfuda::LfudaCache;
use cache_rs::config::LfudaCacheConfig;
use core::num::NonZeroUsize;
let config = LfudaCacheConfig {
capacity: NonZeroUsize::new(2).unwrap(),
initial_age: 0,
max_size: u64::MAX,
};
let mut cache = LfudaCache::init(config, None);
cache.put("a", 1, 1);
cache.put("b", 2, 1);
// contains() does NOT update priority
assert!(cache.contains(&"a"));Sourcepub fn peek<Q>(&self, key: &Q) -> Option<&V>
pub fn peek<Q>(&self, key: &Q) -> Option<&V>
Returns a reference to the value without updating priority or access metadata.
Unlike get(), this does NOT increment the entry’s frequency,
change its priority, or move it between priority lists.
§Example
use cache_rs::lfuda::LfudaCache;
use cache_rs::config::LfudaCacheConfig;
use core::num::NonZeroUsize;
let config = LfudaCacheConfig {
capacity: NonZeroUsize::new(3).unwrap(),
initial_age: 0,
max_size: u64::MAX,
};
let mut cache = LfudaCache::init(config, None);
cache.put("a", 1, 1);
// peek does not change priority
assert_eq!(cache.peek(&"a"), Some(&1));
assert_eq!(cache.peek(&"missing"), None);Source§impl<K: Hash + Eq, V> LfudaCache<K, V>where
V: Clone,
impl<K: Hash + Eq, V> LfudaCache<K, V>where
V: Clone,
Sourcepub fn init(
config: LfudaCacheConfig,
hasher: Option<DefaultHashBuilder>,
) -> LfudaCache<K, V, DefaultHashBuilder>
pub fn init( config: LfudaCacheConfig, hasher: Option<DefaultHashBuilder>, ) -> LfudaCache<K, V, DefaultHashBuilder>
Creates a new LFUDA cache from a configuration.
This is the recommended way to create an LFUDA cache. All configuration
is specified through the LfudaCacheConfig struct, which uses a builder
pattern for optional parameters.
§Arguments
config- Configuration specifying capacity and optional size limit/initial age
§Example
use cache_rs::LfudaCache;
use cache_rs::config::LfudaCacheConfig;
use core::num::NonZeroUsize;
// Simple capacity-only cache
let config = LfudaCacheConfig {
capacity: NonZeroUsize::new(100).unwrap(),
initial_age: 0,
max_size: u64::MAX,
};
let mut cache: LfudaCache<&str, i32> = LfudaCache::init(config, None);
cache.put("key", 42, 1);
// Cache with size limit
let config = LfudaCacheConfig {
capacity: NonZeroUsize::new(1000).unwrap(),
initial_age: 100,
max_size: 10 * 1024 * 1024, // 10MB
};
let cache: LfudaCache<String, Vec<u8>> = LfudaCache::init(config, None);