From 7fd63d8a5db83309fef1e44e1c03239272f58b2c Mon Sep 17 00:00:00 2001 From: Jussi Saurio Date: Fri, 8 Aug 2025 10:32:18 +0300 Subject: [PATCH] btree: cache usable_space in the btreecursor constructor --- core/storage/btree.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/core/storage/btree.rs b/core/storage/btree.rs index 6f21fa15c..4fc0b6245 100644 --- a/core/storage/btree.rs +++ b/core/storage/btree.rs @@ -491,6 +491,11 @@ pub struct BTreeCursor { mv_cursor: Option>>, /// The pager that is used to read and write to the database file. pager: Rc, + /// Cached value of the usable space of a BTree page, since it is very expensive to call in a hot loop via pager.usable_space(). + /// This is OK to cache because both 'PRAGMA page_size' and '.filectrl reserve_bytes' only have an effect on: + /// 1. an uninitialized database, + /// 2. an initialized database when the command is immediately followed by VACUUM. + usable_space_cached: usize, /// Page id of the root page used to go back up fast. root_page: usize, /// Rowid and record are stored before being consumed. @@ -583,10 +588,12 @@ impl BTreeCursor { root_page: usize, num_columns: usize, ) -> Self { + let usable_space = pager.usable_space(); Self { mv_cursor, pager, root_page, + usable_space_cached: usable_space, has_record: Cell::new(false), null_flag: false, going_upwards: false, @@ -4126,8 +4133,11 @@ impl BTreeCursor { Ok(IOResult::Done(())) } + #[inline(always)] + /// Returns the usable space of the current page (which is computed as: page_size - reserved_bytes). + /// This is cached to avoid calling `pager.usable_space()` in a hot loop. fn usable_space(&self) -> usize { - self.pager.usable_space() + self.usable_space_cached } pub fn seek_end(&mut self) -> Result> {