Skip to content

db/datastruct/btindex: interpolation search in BTree leaf#21794

Draft
sudeepdino008 wants to merge 1 commit into
performancefrom
sudeep/bt-interp-search
Draft

db/datastruct/btindex: interpolation search in BTree leaf#21794
sudeepdino008 wants to merge 1 commit into
performancefrom
sudeep/bt-interp-search

Conversation

@sudeepdino008

@sudeepdino008 sudeepdino008 commented Jun 13, 2026

Copy link
Copy Markdown
Member

Search the BTree leaf window by interpolation instead of binary search. Leaf keys are near-uniform, so interpolating on the bytes after the bound keys' common prefix lands near the target — and keeps probes spatially clustered, so cold reads hit far fewer distinct .kv pages.

After a probe budget (BtInterpBudget, default 8) it falls back to binary search, bounding degenerate windows. Default on (BT_INTERP=true). No index/format change; M unchanged (256).

Cold read latency (btnav µs/op, M=256, mainnet 0-8192 files, vmtouch -e, 15k random keys)

domain binary interp (budget 8) speedup
storage 171 108 1.58×
accounts 147 94 1.56×
code 258 109 2.37×

The win is page locality, not fewer probes. Interpolated probes land near the target, so successive probes hit the same/adjacent .kv pages (already faulted); binary's midpoint jumps fault new cold pages. The clearest evidence: on storage, pure interpolation does more probes than binary yet is still fastest cold — so probe count can't be what's driving it.

Probe counts are a secondary, sometimes-counterintuitive metric (sim, 20k keys, budget 8): accounts 7.04→2.86, code 7.04→2.83, storage 7.04→4.30. The budget is exhausted (falling back to binary) only on storage (20 B shared prefix → interpolation estimates degrade) ~10% of the time, never on accounts/code. Pure interpolation (unbounded budget) ties budget 8 on cold latency; budget 8 just caps the worst-case probe tail (storage max 242→16) at ~no latency cost.

Correctness

TestInterpEquivBinary asserts interp returns identical (value, ok, offset) as binary for 50k hits + misses across budgets {0,1,2,4,8,2²⁰}. Existing btree tests pass with interp default-on. Validated on mainnet (storage/accounts/code).

@sudeepdino008 sudeepdino008 marked this pull request as draft June 13, 2026 16:46
Search the BTree leaf window by interpolation instead of binary search:
estimate the target position from the bytes after the bound keys' common
prefix, falling back to binary after BtInterpBudget (8) probes. Default on.

Cold .kv reads speed up 1.5-2.4x because interpolated probes cluster near
the target -> far fewer distinct cold page faults than binary's midpoint
jumps. No index/format change; M unchanged.

Cold btnav us/op (M=256, mainnet 0-8192 files, vmtouch -e, 15k keys):
  storage  171 -> 108 (1.58x)
  accounts 147 ->  94 (1.56x)
  code     258 -> 109 (2.37x)
@AskAlexSharov

AskAlexSharov commented Jun 14, 2026

Copy link
Copy Markdown
Collaborator

On bloatnet:

  • exec: 37tx/s -> 38tx/s (better)
  • majflt: 43K/s -> 38K/s (better)
  • Speed of Storage() read seems 15% faster (based on what i see in pprof)
  • amount of compareKey+Next calls (inside Bt.Get): 300 -> 200

Context:

  • Storage read is not main bottelneck - but speedup .bt is general goodness which will be useful everywhere - for example if switch Commitment.Domain to .bt
  • Existance filters was also added mostly because "non existing key read from MPH causing random .kv heat" - so, switching to .bt maybe reducing existence filters importance (or allow play with

( i benched this PR. not: #21799 )

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces an interpolation-based search strategy when narrowing the B+tree leaf window, aiming to improve cold-read latency by keeping probes spatially clustered in the .kv data file. It adds an environment-controlled toggle and a probe budget, with fallback to binary search.

Changes:

  • Add BT_INTERP / BT_INTERP_BUDGET knobs to enable interpolation search with a bounded probe budget.
  • Extend BpsTree.Get to narrow [l,r) using interpolation estimates (with binary fallback after the budget).
  • Add a new test asserting interpolation search returns identical (value, ok, offset) results as binary search across multiple budgets.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
db/datastruct/btindex/interp_search_test.go Adds an equivalence test comparing interpolation vs binary results across budgets.
db/datastruct/btindex/btree_index.go Introduces env-configurable globals to enable/parameterize interpolation search.
db/datastruct/btindex/bps_tree.go Updates pivot search to return bounding keys and implements interpolation narrowing in Get, plus helpers.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +16 to +19
func TestInterpEquivBinary(t *testing.T) {
t.Parallel()
saveInterp, saveBudget := BtInterp, BtInterpBudget
defer func() { BtInterp, BtInterpBudget = saveInterp, saveBudget }()
Comment on lines +367 to +371
// Interpolation search narrows the window with position estimates from the
// bound keys; after BtInterpBudget probes fall back to binary. The final
// small window is handed to the linear scan below either way.
if BtInterp && len(klo) > 0 && len(khi) > 0 {
probes := uint64(0)
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.

3 participants