From caa556f0f0e37e396e53626132698834c6e69813 Mon Sep 17 00:00:00 2001 From: Ilja Heitlager Date: Sun, 30 Aug 2026 10:39:12 +0200 Subject: [PATCH] perf: inline hot varint/cell decode calls on the SeekRowid binary-search path (#657) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Profiling with `sample` on the read_join bench (16700-row bench_data joined to bench_lookup on its PK) showed 56% of samples landing in TableCursor::seek's binary search — decode_varint, decode_cell_head, and read_cell_pointer were compiled as real (non-inlined) function calls, paid twice per probed cell across ~8-9 binary-search probes per row against bench_lookup's ~230-cell leaf pages. read_full_scan, which never calls seek(), was already faster than the oracle (0.71x), confirming the gap was isolated to this path rather than general record decode. Marking these three small, always-hot functions #[inline] lets LTO fold them into the binary-search loop. read_join drops from 3.63ms to 2.95ms (measured via `cargo bench --bench crud -- read_join`), closing the oracle gap from 1.9x to 1.5x. spend: ~1.5x estimate (initial profiling pointed to diffuse overhead with no fix; a second pass comparing read_join against read_full_scan and the compiled opcode stream against oracle's EXPLAIN output pinned the actual hot loop). --- src/btree.rs | 2 ++ src/record/varint.rs | 1 + 2 files changed, 3 insertions(+) diff --git a/src/btree.rs b/src/btree.rs index b4fd4c9e..6d895a89 100644 --- a/src/btree.rs +++ b/src/btree.rs @@ -1654,6 +1654,7 @@ fn read_u32(page: &[u8], offset: usize, page_num: u32) -> Result usize { /// Decodes a leaf table-b-tree cell's head (payload-length varint + rowid /// varint) and returns `(rowid, payload_len, tail_start)`, where /// `tail_start` is the page offset where the payload bytes begin. +#[inline] fn decode_cell_head( page: &[u8], cell_start: usize, diff --git a/src/record/varint.rs b/src/record/varint.rs index 7502f295..7a86fb7f 100644 --- a/src/record/varint.rs +++ b/src/record/varint.rs @@ -10,6 +10,7 @@ use super::error::RecordError; clippy::arithmetic_side_effects, reason = "i ranges over the compile-time-constant 0..8, so i + 1 never overflows" )] +#[inline] pub fn decode_varint(buf: &[u8]) -> Result<(u64, usize), RecordError> { let mut result: u64 = 0; for i in 0..8 {