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 aBytes::clone(refcount bump), never a chunk-sized memcpy. Insert converts the decompressedVec<u8>once viaBytes::from(vec), which is ZERO-COPY — it reuses theVec’s existing heap allocation rather than allocating a freshArc<[u8]>backing store and memcpy’ing into it (asArc::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 refcountedBytesview of it.BytesisArc-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 callsLruCache::get(which mutates recency — hence aMutex, not anRwLock; but sharded so contention is1/N, never a single process-wide lock). Reuses the testedlrucrate 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. Nounwrap()/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/KeyCacheKeykey-cache model).
Structs§
- Chunk
Key - Authoritative cache key: an SSTable identity hash and a chunk discriminator.
- Decompressed
Chunk Cache - 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.