Skip to content

Commit a21d38e

Browse files
committed
fix(pager): bound the free-list scan to a fixed window per commit
Loading and rewriting the whole durable free-list chain on every write made both the buffer-pool residency and the commit's IO scale with the number of free pages in the store, defeating the bounded-memory budget on the hottest path in the system. begin_write now materialises only a fixed window of the chain (read_chain_prefix / ChainWalk), the allocator cache is loaded from that window alone, and the following commit rewrites just the window and splices the fresh pages onto the untouched retained tail. Callers that need the full entry set (follower reclaim fold, rekey's page walk, fsck-style checks) stream the chain page-by-page instead of materializing it. The free-list module is split into a directory (layout/read/write/budget) along the way, and gains crash-boundary and windowed-rewrite regression coverage.
1 parent 97bcc32 commit a21d38e

21 files changed

Lines changed: 2199 additions & 482 deletions

File tree

.config/nextest.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ test-threads = "num-cpus"
1414
[[profile.default.overrides]]
1515
filter = """
1616
binary(crash_basic)
17+
| binary(crash_boundaries)
1718
| binary(recovery_basic)
1819
| binary(fsck_deep)
1920
| binary(durability)

src/btree/tree/core.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,14 @@ impl<V: Vfs> BTree<V> {
206206

207207
/// Wire in the `Db`'s shared free-page cache. After this call,
208208
/// `allocate_page` pops from the shared pool before bumping `next_page_id`.
209-
/// The pool is loaded at `begin_write` with the durable free-list's
210-
/// floor-safe pages, so recycling from it is always snapshot-safe.
209+
/// The pool is loaded at `begin_write` with the floor-safe pages of the
210+
/// bounded free-list window the following commit rewrites, so recycling
211+
/// from it is always snapshot-safe.
212+
///
213+
/// The pool is draw-only: nothing here may push into it. The commit deletes
214+
/// a recycled id from the chain by finding it in that window, so an id
215+
/// pushed in from elsewhere would be handed out while the unscanned tail
216+
/// still named it — the same page id given to two live structures.
211217
pub fn set_free_page_cache(&mut self, cache: Arc<parking_lot::Mutex<Vec<u64>>>) {
212218
self.free_page_cache = Some(cache);
213219
}

0 commit comments

Comments
 (0)