Skip to content

perf(lite): decouple reads from commit I/O and reuse LSM leases - #1018

Merged
ajroetker merged 6 commits into
mainfrom
codex/lite-reader-lsm-leases
Oct 8, 2026
Merged

ajroetker merged 6 commits into
mainfrom
codex/lite-reader-lsm-leases

Conversation

@ajroetker

@ajroetker ajroetker commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Lite readers could wait behind commit disk I/O, and repeated LSM reads recreated artifact sources or copied entire decoded blocks. This change publishes read snapshots behind a short read fence, reuses artifact-specific sources, and borrows immutable decoded blocks with explicit result lifetimes.

  • Reader admission and normal release avoid the writer I/O mutex. An atomic reader frontier protects page reuse; index adapters use the snapshot's pinned descriptor across vacuum and inode replacement.
  • Artifact sources retain only their immutable roots. Active cursors keep their sources valid; idle sources release their descriptors, buffers, markers, and retired-inode accounting before rewrite admission or when their generation retires. Active sources remain charged during admission, and expired cache entries reopen lazily. Teardown snapshots marker cleanup eligibility under the lifetime lock before entering publication. Idle cache retention is capped at 16.
  • Source eviction, provider acquisition, creation, and destruction run outside the shared source-cache lock. Concurrent cold reads of one path share an in-flight open, including its error result, without serializing unrelated paths.
  • Local decoded blocks use reference-counted buffers. Point reads borrow the located row and copy only the returned value. Prefix and prefix-plus-Snappy point reads check the warm decoded cache before allocating compressed lookup scratch; cold point reads keep their direct compressed lookup. Local and external block leases share transaction result retention; adjacent batch values retain one pin per resident block. Local result pins are capped at 1 MiB and 64 blocks per owner, then values are copied. The copy/borrow decision is reused for later rows in the same block. Returned values survive cursor close and cache eviction.

The SQL spill manager guards native directory operations on freestanding targets and reports the existing SQL resource-limit error when native spill is required.

The .aflite format and public C ABI are unchanged. This PR is independent of the derived-contention fixes in #1016.

Validation and measurements:

  • Final native Debug regression suite after the main merge: 786 passed, 21 existing opt-in benchmark/helper skips, zero failures or leaks. Covers the affected LSM/Lite paths, segment sources, allocation-failure cleanup, and native SQL spill. The admission fixture preserves active reads under a tight cap and expires cache-only sources; the teardown fixture retires a source while its final catalog mutation is blocked. An earlier focused run passed 134 tests with zero failures or leaks.
  • 16 concurrent native reads create one catalog lease. Eight readers share one failed provider open and a later retry succeeds.
  • 4,096 warm hits on a 32 KiB decoded block: zero payload allocations versus 4,096 copies / 128 MiB in the reference mechanism.
  • In the original two-key compressed-read fixture, 100 warm point reads made 500 backend allocations and 100 encoded-block loads. The updated fixtures cover both prefix-only and prefix-plus-Snappy blocks, with the backend heap budget frozen during warm reads, and make zero backend allocations and zero encoded-block loads; owned values still copy to the result allocator.
  • A warm five-byte point result makes one five-byte result allocation and zero backend allocations. A two-value local-cache batch retains one block pin and makes zero value copies; both results survive cache eviction.
  • 128 reads and releases complete while writer fsync is deliberately blocked; the same fixture on main times out after two seconds. Existing snapshots retain old values and new snapshots see the commit.
  • A native merge cursor reads 48 documents across 24 persisted overlapping runs, preserving active sources and trimming idle entries after close.
  • Final WASM rebuild passed: platform counters, float16 SIMD, host entropy, and the embedded shared smoke test.
  • Deterministic results are checked in at zig/bench/baselines/lite-reader-lsm-leases.json.

Cold decoding/source creation, cursor and result-pin metadata, and owned point results still allocate. These are allocation, contention, and lifetime measurements; they do not establish end-to-end throughput or a 2 GiB soak result.

@ajroetker
ajroetker merged commit 84dfbf5 into main Oct 8, 2026
4 of 7 checks passed
@ajroetker
ajroetker deleted the codex/lite-reader-lsm-leases branch October 8, 2026 17:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant