Skip to main content

Module cache

Module cache 

Source
Expand description

Shared, bytes-bounded, sharded decompressed-chunk cache (issue #1567). Shared, bytes-bounded, sharded decompressed-chunk cache (issue #1567, Epic B/B1).

A cache of decompressed SSTable compression chunks keyed by authoritative (sstable identity, chunk index). It is the single biggest lever for repeated-read latency identified by the July 2026 read-path audit: every wired read site consults it before reading+decompressing, so a repeat read of a resident chunk is a refcount bump instead of a disk read + decompress.

§Design (owner decision #1, LOCKED — see

openspec/changes/decompressed-chunk-cache/design.md)

  • Value = bytes::Bytes (D3; substrate migration issue #1940): a hit is a Bytes::clone (refcount bump), never a chunk-sized memcpy. Insert converts the decompressed Vec<u8> once via Bytes::from(vec), which is ZERO-COPY — it reuses the Vec’s existing heap allocation rather than allocating a fresh Arc<[u8]> backing store and memcpy’ing into it (as Arc::from(boxed_slice) did). This is what lets the windowed scan reach ≤1 alloc/chunk: the single decompress-output allocation flows all the way into the cache untouched, and a window fill borrows a refcounted Bytes view of it. Bytes is Arc-backed, so the refcount-bump-on-hit contract is preserved verbatim.
  • Bytes-bounded, not entry-count (spec R1): each entry is weighed by its decompressed length; after an insert the owning shard evicts LRU entries until it is within its byte budget. A single entry larger than the budget is retained (we never evict below one live entry) — the read path must always be able to return the chunk it just produced.
  • Hand-sharded Mutex<LruCache> (D2): shards.len() is a power of two. The hit path locks exactly ONE shard and calls LruCache::get (which mutates recency — hence a Mutex, not an RwLock; but sharded so contention is 1/N, never a single process-wide lock). Reuses the tested lru crate internals; no new external dependency.
  • Poison-tolerant (D2): every lock is taken with lock().unwrap_or_else(|e| e.into_inner()) so one panicking thread cannot turn the cache into a panic-for-everyone. No unwrap()/expect() here.
  • No-heuristics (mandate #28): keys are (u64 sstable id, u64 chunk index) derived from authoritative reader identity + chunk offsets — never inferred from decompressed byte content.

The default is a Box<[Mutex<Shard>]> rather than a fixed [Mutex<Shard>; N] array so the shard count is a constructor parameter: production uses [DEFAULT_SHARDS], while unit tests use a single shard for deterministic eviction ordering. Both remain power-of-two hand-sharded Mutex<LruCache> — the design intent is preserved.

Re-exports§

pub use global_key_offset::GenerationIdentity;
pub use global_key_offset::GlobalKeyOffsetCache;
pub use global_key_offset::PartitionLoc;
pub use global_key_offset::DEFAULT_GLOBAL_KEY_CACHE_BYTES;
pub use global_key_offset::DEFAULT_GLOBAL_KEY_CACHE_SHARDS;

Modules§

global_key_offset
Process-global, byte-bounded, sharded key→partition-offset cache (issue #2059, Epic B / memory lane; Cassandra’s AutoSavingCache/KeyCacheKey key-cache model).

Structs§

ChunkKey
Authoritative cache key: an SSTable identity hash and a chunk discriminator.
DecompressedChunkCache
A shared, bytes-bounded, sharded decompressed-chunk cache.

Constants§

DEFAULT_BUDGET_BYTES
Default total byte budget when a cache is constructed without an explicit budget (mirrors config.memory.block_cache.max_size’s 256 MiB default).
DEFAULT_SHARDS
Default shard count (power of two). Production readers use this via DecompressedChunkCache::with_budget_bytes.