Skip to content

F1: Drop BP's rank_l2 (largest remaining select/rank memory win) #596

Description

@newhoggy

Status (rescoped 2026-08-08, updated 2026-08-08)

Unblocked — #665's rank1 micro-benchmark merged. benches/bp_rank_micro.rs now covers BalancedParens::rank1 across flat/deep/mixed tree shapes at 1K-1M opens, benchmark-only (no src/ changes). Pre-#596 baseline (10,000 rank1() queries/batch, µs):

Platform 1K 10K 100K 1M
ARM (M4 Pro) ~11.5 ~11.6 ~11.9 ~12.8
x86_64 (Zen 4 7950X) ~26.7 ~24.4 ~24.7 ~27.9

Shape (flat/deep/mixed) is neutral on both platforms — expected, since the current rank_l2 decode is a pure shift-and-mask independent of bit content; size drives the difference, with 1M falling out of cache on both architectures. This is the number any #596 implementation attempt should diff against on both rank1 (via this bench) and select1 (via the existing benches/bp_select_micro.rs, from #64) — both consumers still apply, this issue is otherwise unchanged from the assessment below.


Summary

rank_l2: Vec<u64> in BalancedParens costs 64 bits per 512-bit block =
12.5% of the BP bitmap — twice what #64's Step B saved. Poppy's actual
trade is to omit the per-word level and popcount up to 7 words inside a basic
block, which is exactly one 64-byte cache line and one the query must load
anyway for the partial word.

Why now

Interacts with #64's Step B, but not the way this issue originally stated.

The claim was that once select drove off rank_l1, rank_l2 would be left
with rank1 as its only consumer. That is wrong as #64 was implemented:
WithCsPoppy::select1 reads rank_l2 too, unpacking its 9-bit per-word
offsets (step 3 of its query) to land on the exact word without popcounting.
rank_l2 now has two consumers, not one.

That makes this issue more expensive than "delete an array", not less.
Dropping rank_l2 forces select1 back to popcounting up to 7 words inside
the block — reintroducing exactly the word scanning Step B removed, and most
likely widening the ARM select1 regression #64 measured (+6-14% micro, +7.4%
end-to-end on M4 Pro). Budget for changing both query paths, and re-run
bp_select_micro alongside the rank-side measurement rather than treating this
as rank-only work.

BP rank1 is very hot (cursor navigation), so the rank side remains a genuine
space/time trade needing end-to-end measurement, not a free reduction. Should
follow #64 so the select path isn't confounded with this change.

Deferred from

#64 (docs/plan/cspoppy.md §6, F1) — not scheduled, recorded so the reasoning
isn't lost.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions