btree/tablebtree_move_to: micro-optimizations

This commit is contained in:
Jussi Saurio
2025-04-26 11:32:24 +03:00
parent 0d77ea9446
commit 23ae5a27c4
3 changed files with 25 additions and 22 deletions

View File

@@ -1043,18 +1043,8 @@ impl BTreeCursor {
loop {
if min > max {
if let Some(leftmost_matching_cell) = leftmost_matching_cell {
self.stack.set_cell_index(leftmost_matching_cell as i32);
let matching_cell = contents.cell_get(
leftmost_matching_cell,
payload_overflow_threshold_max(
contents.page_type(),
self.usable_space() as u16,
),
payload_overflow_threshold_min(
contents.page_type(),
self.usable_space() as u16,
),
self.usable_space(),
let left_child_page = contents.cell_table_interior_read_left_child_page(
leftmost_matching_cell as usize,
)?;
// If we found our target rowid in the left subtree,
// we need to move the parent cell pointer forwards or backwards depending on the iteration direction.
@@ -1064,15 +1054,11 @@ impl BTreeCursor {
// this parent: rowid 666
// left child has: 664,665,666
// we need to move to the previous parent (with e.g. rowid 663) when iterating backwards.
self.stack.next_cell_in_direction(iter_dir);
let BTreeCell::TableInteriorCell(TableInteriorCell {
_left_child_page,
..
}) = matching_cell
else {
unreachable!("unexpected cell type: {:?}", matching_cell);
};
let mem_page = self.pager.read_page(_left_child_page as usize)?;
let index_change =
-1 + (iter_dir == IterationDirection::Forwards) as i32 * 2;
self.stack
.set_cell_index(leftmost_matching_cell as i32 + index_change);
let mem_page = self.pager.read_page(left_child_page as usize)?;
self.stack.push(mem_page);
continue 'outer;
}
@@ -1089,7 +1075,6 @@ impl BTreeCursor {
}
}
let cur_cell_idx = (min + max) / 2;
self.stack.set_cell_index(cur_cell_idx as i32);
let cell_rowid = contents.cell_table_interior_read_rowid(cur_cell_idx as usize)?;
// in sqlite btrees left child pages have <= keys.
// table btrees can have a duplicate rowid in the interior cell, so for example if we are looking for rowid=10,

View File

@@ -617,6 +617,23 @@ impl PageContent {
Ok(rowid)
}
/// Read the left child page of a table interior cell.
#[inline(always)]
pub fn cell_table_interior_read_left_child_page(&self, idx: usize) -> Result<u32> {
assert!(self.page_type() == PageType::TableInterior);
let buf = self.as_ptr();
const INTERIOR_PAGE_HEADER_SIZE_BYTES: usize = 12;
let cell_pointer_array_start = INTERIOR_PAGE_HEADER_SIZE_BYTES;
let cell_pointer = cell_pointer_array_start + (idx * 2);
let cell_pointer = self.read_u16(cell_pointer) as usize;
Ok(u32::from_be_bytes([
buf[cell_pointer],
buf[cell_pointer + 1],
buf[cell_pointer + 2],
buf[cell_pointer + 3],
]))
}
/// Read the rowid of a table leaf cell.
#[inline(always)]
pub fn cell_table_leaf_read_rowid(&self, idx: usize) -> Result<u64> {

View File

@@ -1402,6 +1402,7 @@ impl SeekOp {
/// A seek with SeekOp::LE implies:
/// Find the last table/index key that compares less than or equal to the seek key
/// -> used in backwards iteration.
#[inline(always)]
pub fn iteration_direction(&self) -> IterationDirection {
match self {
SeekOp::EQ | SeekOp::GE | SeekOp::GT => IterationDirection::Forwards,