Skip to content

db/datastruct/btindex: EF-encode .bt pivot offsets - #21893

Merged
AskAlexSharov merged 1 commit into
alex/bt_ram_36from
sudeep/bt-nodeofft-ef
Jun 19, 2026
Merged

AskAlexSharov merged 1 commit into
alex/bt_ram_36from
sudeep/bt-nodeofft-ef

Conversation

@sudeepdino008

@sudeepdino008 sudeepdino008 commented Jun 19, 2026 •

Copy link
Copy Markdown
Member

Stacks on #21875. After that PR, the .bt pivot cache's only per-node heap cost is the offset array — a flat []uint64 (8 B/node). Those offsets are strictly increasing, so this stores them Elias-Fano-encoded (~7 bits/node) as the only representation: no flat array, no toggle.

The EF is built at open, directly from the existing nodes section — no on-disk format change, and both layouts are covered (v2 footer and v0 legacy list).

Heap (open pivot cache, commitment, M=256)

file pivots (N/M) flat []uint64 (before) EF (this PR)
141M keys 543K 4.35 MB 0.46 MB (9.5×)
1M keys 4.2K 34 KB 5 KB

≈ 6.8 bits/pivot. On a mainnet node the aggregate pivot heap (storage-dominated, ~340 MB after #21875) drops to ~36 MB.

Latency / major-faults (cold = evicted page cache, 15k sampled keys)

file variant cold µs/op cold faults/op warm µs/op
141M keys flat 140 1.57 10
141M keys EF 143 1.57 8
1M keys flat 180 2.54 6
1M keys EF 181 2.54 7

Identical fault count, latency within run-to-run noise: the extra EF.Get calls in the pivot search are pure CPU and don't register against the ~80 µs/major-fault cost.

Tests

Test_BtreeIndex_NodeOfftEF_V0_V2 opens both v0 and v2 files and checks every key resolves to its true .kv value through the EF-decoded pivots. decodeNodes / decodeListNodesV0 unit tests updated for the EF return. Full btindex suite passes.

@sudeepdino008 sudeepdino008 changed the title db/datastruct/btindex: Elias-Fano-encode .bt pivot offsets (nodeOfft) db/datastruct/btindex: EF-encode .bt pivot offsets Jun 19, 2026
@sudeepdino008
sudeepdino008 force-pushed the sudeep/bt-nodeofft-ef branch from d68a2f3 to fbbde06 Compare June 19, 2026 02:18
The pivot cache's only per-node heap cost was nodeOfft (a flat []uint64, 8 B/node).
The offsets are strictly increasing, so store them Elias-Fano-encoded (~7 bits/node)
as the sole representation — no flat array, no toggle. The EF is built at open
directly from the existing nodes section; no on-disk format change. decodeNodes
(v2 footer) and decodeListNodesV0 (legacy) build it for both layouts, WarmUp for
the no-nodes-section path.

On commitment 141M keys (M=256): pivot heap 4.35 MB -> 0.46 MB (~9.5x); lookup
latency and major-faults/op unchanged.
@sudeepdino008
sudeepdino008 force-pushed the sudeep/bt-nodeofft-ef branch from fbbde06 to af28239 Compare June 19, 2026 03:45
@AskAlexSharov

Copy link
Copy Markdown
Collaborator

i guess we can add it to .bt (to speedup startup). but i would do it after #20180 (because maybe it will work well - but may require "another datastructure" than EF of offsets)

@AskAlexSharov

Copy link
Copy Markdown
Collaborator
┌──────────────────────┬───────────────────────┬────────────────┬────────┐
  │      Benchmark       │ sudeep/bt-nodeofft-ef │ alex/bt_ram_36 │   Δ    │
  ├──────────────────────┼───────────────────────┼────────────────┼────────┤
  │ BpsTreeSeek          │ 670.6 ns/op           │ 566.0 ns/op    │ −15.6% │
  ├──────────────────────┼───────────────────────┼────────────────┼────────┤
  │ BpsTreeGet           │ 539.9 ns/op           │ 424.5 ns/op    │ −21.4% │
  ├──────────────────────┼───────────────────────┼────────────────┼────────┤
  │ BpsTree_bs/N1M_M256  │ 167.3 ns/op           │ 47.5 ns/op     │ −71.6% │
  ├──────────────────────┼───────────────────────┼────────────────┼────────┤
  │ BpsTree_bs/N1M_M64   │ 175.9 ns/op           │ 50.8 ns/op     │ −71.1% │
  ├──────────────────────┼───────────────────────┼────────────────┼────────┤
  │ BpsTree_bs/N10M_M256 │ 202.8 ns/op           │ 59.4 ns/op     │ −70.7% │
  ├──────────────────────┼───────────────────────┼────────────────┼────────┤
  │ BtIndex_Get/M256     │ 474.2 ns/op           │ 349.2 ns/op    │ −26.4% │
  ├──────────────────────┼───────────────────────┼────────────────┼────────┤
  │ BtIndex_Get/M128     │ 474.0 ns/op           │ 352.0 ns/op    │ −25.7% │
  ├──────────────────────┼───────────────────────┼────────────────┼────────┤
  │ BtIndex_Get/M64      │ 475.6 ns/op           │ 350.3 ns/op    │ −26.3% │
  ├──────────────────────┼───────────────────────┼────────────────┼────────┤
  │ BtIndex_Get/M32      │ 476.5 ns/op           │ 347.8 ns/op    │ −27.0% │
  └──────────────────────┴───────────────────────┴────────────────┴────────┘

@sudeepdino008

Copy link
Copy Markdown
Member Author
┌──────────────────────┬───────────────────────┬────────────────┬────────┐
  │      Benchmark       │ sudeep/bt-nodeofft-ef │ alex/bt_ram_36 │   Δ    │
  ├──────────────────────┼───────────────────────┼────────────────┼────────┤
  │ BpsTreeSeek          │ 670.6 ns/op           │ 566.0 ns/op    │ −15.6% │
  ├──────────────────────┼───────────────────────┼────────────────┼────────┤
  │ BpsTreeGet           │ 539.9 ns/op           │ 424.5 ns/op    │ −21.4% │
  ├──────────────────────┼───────────────────────┼────────────────┼────────┤
  │ BpsTree_bs/N1M_M256  │ 167.3 ns/op           │ 47.5 ns/op     │ −71.6% │
  ├──────────────────────┼───────────────────────┼────────────────┼────────┤
  │ BpsTree_bs/N1M_M64   │ 175.9 ns/op           │ 50.8 ns/op     │ −71.1% │
  ├──────────────────────┼───────────────────────┼────────────────┼────────┤
  │ BpsTree_bs/N10M_M256 │ 202.8 ns/op           │ 59.4 ns/op     │ −70.7% │
  ├──────────────────────┼───────────────────────┼────────────────┼────────┤
  │ BtIndex_Get/M256     │ 474.2 ns/op           │ 349.2 ns/op    │ −26.4% │
  ├──────────────────────┼───────────────────────┼────────────────┼────────┤
  │ BtIndex_Get/M128     │ 474.0 ns/op           │ 352.0 ns/op    │ −25.7% │
  ├──────────────────────┼───────────────────────┼────────────────┼────────┤
  │ BtIndex_Get/M64      │ 475.6 ns/op           │ 350.3 ns/op    │ −26.3% │
  ├──────────────────────┼───────────────────────┼────────────────┼────────┤
  │ BtIndex_Get/M32      │ 476.5 ns/op           │ 347.8 ns/op    │ −27.0% │
  └──────────────────────┴───────────────────────┴────────────────┴────────┘

yeah, cpu will be more because of ef; things i cared about more -- not much effect on majfaults + heap reduction and fast startup.

@AskAlexSharov
AskAlexSharov merged commit 0106420 into alex/bt_ram_36 Jun 19, 2026
1 check passed
@AskAlexSharov
AskAlexSharov deleted the sudeep/bt-nodeofft-ef branch June 19, 2026 08:50
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.

2 participants