Micro Moka
A fast, lightweight, single-threaded cache for Rust. Forked from Mini Moka and stripped down to the essentials: no async, no concurrency overhead, no weight-based eviction, no TTL. Just a bounded cache with the W-TinyLFU eviction policy from Caffeine -- the same algorithm that powers some of the highest hit-ratio caches in production.
The goal is simple: be the fastest single-threaded cache in Rust.
use Cache;
let mut cache = new;
cache.insert;
assert_eq!;
Why Micro Moka?
W-TinyLFU is a better eviction policy. Standard LRU caches are vulnerable to scan pollution -- a single sequential scan can flush the entire cache. W-TinyLFU uses a frequency sketch (Count-Min Sketch with 4-bit counters) to admit only entries that are likely to be accessed again, producing significantly higher hit ratios on real-world workloads compared to LRU, FIFO, or CLOCK.
Minimal overhead. One production dependency (hashbrown). No allocator, no async runtime, no parking lot, no unsafe code. Compiles fast, produces small binaries.
Single-threaded by design. No Arc, no Mutex, no atomic operations. If your cache lives on one thread -- CLI tools, WASM, game loops, compilers, single-threaded servers -- you pay zero synchronization cost.
Installation
[]
= "0.1"
Usage
use Cache;
// Create with capacity
let mut cache: = new;
// Or use the builder
let mut cache: = builder
.max_capacity
.initial_capacity
.build;
// Insert and retrieve
cache.insert;
assert_eq!;
// Check membership
assert!;
// Remove entries
cache.invalidate;
let removed = cache.remove; // returns Option<V>
// Bulk invalidation
cache.invalidate_entries_if;
cache.invalidate_all;
// Inspection
let count = cache.entry_count;
let policy = cache.policy;
println!;
// Iteration (does not update access order)
for in cache.iter
Custom Hashers
The default hasher is RandomState (SipHash). For cache-heavy workloads, a faster hasher like aHash can improve throughput substantially:
use Cache;
let mut cache: = builder
.max_capacity
.build_with_hasher;
How W-TinyLFU Works
On every cache access, a probabilistic frequency counter (Count-Min Sketch) records how often keys are requested. When the cache is full and a new entry arrives:
- The candidate (new entry) is compared against victims (least-recently-used entries from the eviction queue)
- If the candidate's estimated frequency exceeds the victims', it is admitted and the victims are evicted
- If not, the candidate is rejected -- preventing low-frequency entries from displacing popular ones
The frequency sketch uses 4-bit counters with periodic aging (halved when a sample threshold is reached), keeping memory usage bounded regardless of the key universe size. The sketch is only enabled once the cache reaches 50% capacity, avoiding overhead during warmup.
What Was Removed from Mini Moka
| Feature | Rationale |
|---|---|
sync module (concurrent cache) |
Eliminates DashMap, locks, atomics |
| Async support | No runtime dependency |
Weight-based eviction (Weigher) |
All entries cost 1 slot; simpler admission |
| TTL / TTI expiration | No timer overhead; entries live until evicted or invalidated |
smallvec, tagptr, triomphe dependencies |
Simplified internals |
Minimum Supported Rust Version
| Feature | MSRV |
|---|---|
| Default | Rust 1.76.0 (Feb 8, 2024) |
MSRV follows a rolling 6-month policy. Bumping MSRV is not considered a semver-breaking change.
Development
# All tests (including compile-fail and doc tests)
RUSTFLAGS='--cfg trybuild'
# Clippy (CI treats warnings as errors)
# Format
# Docs (nightly)
# Miri
Releases
Automated on merge to main. See RELEASING.md for details.
Credits
Architecture inspired by Caffeine for Java. Thanks to Ben Manes and all Caffeine contributors.
Forked from Mini Moka by Tatsuya Kawano and the Moka contributors.
License
MIT OR Apache-2.0. See LICENSE-MIT and LICENSE-APACHE.