Skip to main content

Crate cachekit

Crate cachekit 

Source
Expand description

High-performance cache primitives with pluggable eviction policies.

cachekit provides a trait-based cache framework with 18 eviction policies, arena-backed data structures, and optional metrics — all designed for allocation-free hot paths and predictable tail latency.

§Quick Start

The fastest way to get a cache is through the builder module:

use cachekit::builder::{CacheBuilder, CachePolicy};

let mut cache = CacheBuilder::new(1000).build::<u64, String>(CachePolicy::Lru);
cache.insert(1, "hello".to_string());
assert_eq!(cache.get(&1), Some(&"hello".to_string()));

For direct access to policy-specific APIs, use the concrete types:

use cachekit::policy::lru_k::LrukCache;
use cachekit::traits::{CoreCache, LrukCacheTrait};

let mut cache = LrukCache::with_k(1000, 2);
cache.insert(42, "value");
cache.get(&42); // second access — now scan-resistant
assert!(cache.k_distance(&42).is_some());

§Architecture

┌──────────────────────────────────────────────────────────────────────┐
│                          cachekit                                    │
│                                                                      │
│   traits        Trait hierarchy (ReadOnlyCache → CoreCache → …)      │
│   builder       Unified CacheBuilder + Cache<K,V> wrapper            │
│   policy        17 eviction policies behind feature flags            │
│   ds            Arena, ring buffer, intrusive list, ghost list, …    │
│   store         Storage backends (HashMap, slab, weighted)           │
│   metrics       Hit/miss counters and snapshots (feature-gated)      │
│   error         ConfigError and InvariantError types                 │
└──────────────────────────────────────────────────────────────────────┘

Policy ↔ Storage separation. Policies only manage metadata and eviction ordering; the underlying storage is a separate concern. This lets each policy use the most cache-friendly layout (contiguous arenas, ring buffers, frequency buckets) without coupling to a single map implementation.

§Trait Hierarchy

All caches implement traits::CoreCache, which extends traits::ReadOnlyCache. Policy-specific behaviour is expressed through additional traits:

TraitExtendsPurpose
ReadOnlyCachecontains, len, capacity (no side effects)
CoreCacheReadOnlyCacheinsert, get, clear
MutableCacheCoreCacheremove (not available on FIFO)
FifoCacheTraitCoreCachepop_oldest, age_rank
LruCacheTraitMutableCachepop_lru, touch, recency_rank
LfuCacheTraitMutableCachepop_lfu, frequency
LrukCacheTraitMutableCachepop_lru_k, k_distance

Write generic code against the trait you need:

use cachekit::traits::{CoreCache, ReadOnlyCache};

fn utilization<K, V, C: ReadOnlyCache<K, V>>(cache: &C) -> f64 {
    cache.len() as f64 / cache.capacity() as f64
}

§Eviction Policies

Each policy is gated behind a policy-* feature flag. The default feature set enables S3-FIFO, LRU, Fast-LRU, LRU-K, and Clock. Enable policy-all for everything.

PolicyFeatureEviction basisComplexityBest for
FIFOpolicy-fifoInsertion orderO(1)Streaming, predictable eviction
LRUpolicy-lruRecencyO(1)Temporal locality
Fast-LRUpolicy-fast-lruRecency (no Arc)O(1)Max single-threaded throughput
LRU-Kpolicy-lru-kK-th access timeO(1)Scan resistance (databases)
LFUpolicy-lfuFrequency (buckets)O(1)Stable hot spots
Heap-LFUpolicy-heap-lfuFrequency (heap)O(log n)Large caches, frequent eviction
2Qpolicy-two-qTwo-queue promotionO(1)Mixed workloads
S3-FIFOpolicy-s3-fifoThree-queue FIFOO(1)CDN, scan-heavy workloads
ARCpolicy-arcAdaptive recency/freqO(1)Unknown/changing workloads
CARpolicy-carClock + ARCO(1)Adaptive with low overhead
SLRUpolicy-slruSegmented LRUO(1)Buffer pools, scans
Clockpolicy-clockReference bitO(1) amortisedLow-overhead LRU approx
Clock-PROpolicy-clock-proAdaptive clockO(1) amortisedScan-resistant clock
NRUpolicy-nruNot-recently-used bitO(n) worst caseSmall caches, coarse recency
LIFOpolicy-lifoReverse insertionO(1)Stack-like / undo buffers
MRUpolicy-mruMost recent accessO(1)Cyclic / sequential scans
MFUpolicy-mfuHighest frequencyO(1)Niche inverse-frequency
Randompolicy-randomUniform randomO(1)Baselines

§Feature Flags

FlagDefaultDescription
policy-s3-fifoyesS3-FIFO policy
policy-lruyesLRU policy
policy-fast-lruyesFast-LRU (no Arc wrapping)
policy-lru-kyesLRU-K policy
policy-clockyesClock (second-chance) policy
policy-allnoEnable every policy
metricsnoHit/miss counters, metrics::snapshot::CacheMetricsSnapshot
concurrencynoparking_lot-backed concurrent data structures

Disable defaults and cherry-pick for smaller builds:

[dependencies]
cachekit = { version = "0.x", default-features = false, features = ["policy-s3-fifo"] }

§Data Structures (ds)

The ds module exposes the building blocks used by policies:

All structures pre-allocate and reuse memory; none allocate on the hot path.

§Thread Safety

Individual caches are not thread-safe by default. Options:

  1. Wrap in Arc<RwLock<Cache>> for coarse-grained sharing.
  2. Enable the concurrency feature for parking_lot-backed concurrent variants (ConcurrentClockRing, ConcurrentSlotArena, etc.).
  3. Use the ConcurrentCache marker trait to constrain generic code to thread-safe implementations.

§Metrics

Enable the metrics feature to get lightweight hit/miss/eviction counters. Detailed snapshots are available via CacheMetricsSnapshot.

§Error Handling

Fallible constructors (e.g. S3FifoCache::try_with_ratios) return ConfigError for invalid parameters. Debug-only invariant checks produce InvariantError.

§Choosing a Policy

                   ┌─ temporal locality? ──► LRU / Fast-LRU
                   │
 What does your ───┼─ frequency matters? ──► LFU / Heap-LFU
 workload look     │
 like?             ├─ scan-heavy / mixed? ─► S3-FIFO / 2Q / LRU-K / ARC
                   │
                   ├─ unknown / changing? ──► ARC / Clock-PRO
                   │
                   └─ simple / streaming? ──► FIFO / Clock

Modules§

builder
Unified cache builder for all eviction policies.
ds
error
Error types for the cachekit library.
metrics
policy
prelude
store
traits
Cache Trait Hierarchy