Skip to content

Optimize leaf prefix search benchmarks - #1635

Open
snissn wants to merge 2 commits into
mainfrom
codex/leaf-prefix-search-bench-prod-opt
Open

Optimize leaf prefix search benchmarks#1635
snissn wants to merge 2 commits into
mainfrom
codex/leaf-prefix-search-bench-prod-opt

Conversation

@snissn

@snissn snissn commented May 19, 2026

Copy link
Copy Markdown
Owner

Summary

  • optimize production prefix leaf search by reconstructing each fallback key before comparison and removing the now-unused virtual prefix comparator
  • keep the Rust/C/matched-Go leaf benchmark harnesses aligned with explicit fixed-BE8 and variable-length key cases
  • add the variable-length search row to the smoke benchmark summary

Validation

  • cargo build --release --manifest-path experiments/rust_leaf_bench/Cargo.toml
  • cc -O3 -std=c11 -Wall -Wextra experiments/rust_leaf_bench/matched_c/main.c -o /tmp/treedb_leaf_matched_c_pr_check
  • go test ./TreeDB/node -run 'TestLeafColumnarPrefix|TestLeafPrefix|TestLeafColumnar' -count=1
  • go test ./TreeDB/node -run '^$' -bench 'BenchmarkSearchLeaf_(PrefixV2|ColumnarPrefixV2)$' -benchtime=2s -count=3

Focused prefix benchmark on this branch:

BenchmarkSearchLeaf_PrefixV2-8            190.3 ns/op
BenchmarkSearchLeaf_PrefixV2-8            188.4 ns/op
BenchmarkSearchLeaf_PrefixV2-8            188.4 ns/op
BenchmarkSearchLeaf_ColumnarPrefixV2-8     84.88 ns/op
BenchmarkSearchLeaf_ColumnarPrefixV2-8     86.81 ns/op
BenchmarkSearchLeaf_ColumnarPrefixV2-8     85.40 ns/op

For comparison, clean origin/main in the same temporary worktree measured:

BenchmarkSearchLeaf_PrefixV2-8            230.1 ns/op
BenchmarkSearchLeaf_PrefixV2-8            230.3 ns/op
BenchmarkSearchLeaf_PrefixV2-8            230.8 ns/op
BenchmarkSearchLeaf_ColumnarPrefixV2-8    122.1 ns/op
BenchmarkSearchLeaf_ColumnarPrefixV2-8    121.4 ns/op
BenchmarkSearchLeaf_ColumnarPrefixV2-8    121.0 ns/op

Final integrated smoke:

  • BENCHTIME=2s ./run_leaf_smoke.sh

Key rows from the final smoke:

BenchmarkSearchLeaf_PrefixV2-8                   202.9 ns/op
BenchmarkSearchLeaf_ColumnarPrefixV2-8            86.52 ns/op
MATCHED_GO search/prefix_v2                       83.86 ns/op
MATCHED_GO search/columnar_prefix_v2              79.71 ns/op
MATCHED_C  search/prefix_v2                       71.80 ns/op
MATCHED_C  search/columnar_prefix_v2              77.51 ns/op
RESULT     search/prefix_v2                       69.53 ns/op
RESULT     search/columnar_prefix_v2              62.98 ns/op

Summary by CodeRabbit

  • New Features

    • Added benchmark and runtime support for variable-length keys and a new fixed-8-byte key mode.
  • Refactor

    • Simplified leaf search comparison to always compare reconstructed keys for prefix-compressed pages.
    • Converted storage to fixed-size arena allocations from heap-backed vectors.
  • Chores

    • Updated benchmark scripts and harnesses to include the new columnar variable-length case.

Review Change Stack

Copilot AI review requested due to automatic review settings May 19, 2026 17:05
@coderabbitai

coderabbitai Bot commented May 19, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 22a05bb9-07a2-4977-b7e5-301bcb4a0c05

📥 Commits

Reviewing files that changed from the base of the PR and between 6370270 and 4ddce22.

📒 Files selected for processing (1)
  • experiments/rust_leaf_bench/matched_c/main.c

📝 Walkthrough

Walkthrough

This PR refactors leaf search comparison logic across Go, C, and Rust implementations by removing virtual-key comparators and reconstructing prefix+suffix keys for direct comparison. It adds KeyKind infrastructure to support variable-length and fixed 8-byte big-endian key representations, introduces variable-length key benchmarking tables and generators, optimizes Rust internal storage from heap vectors to fixed-size arrays, and wires new benchmark cases into the test suite.

Changes

Leaf search refactoring and variable-length key support

Layer / File(s) Summary
Virtual-key comparison removal and reconstruction logic
TreeDB/node/leaf.go, experiments/rust_leaf_bench/matched_c/main.c, experiments/rust_leaf_bench/matched_go/main.go, experiments/rust_leaf_bench/src/main.rs
Removes compareLeafPrefixVirtualKey, compareSmallBigEndian, and compare_prefix_virtual_key helpers. Updates searchLeafPrefixBlock and searchLeafColumnarPrefixV2BlockWithMeta to reconstruct prevKey from prefix+suffix pieces and compare via compareLeafKey instead of virtual-key comparators. Simplifies compareLeafKey across all implementations to use direct byte comparison without 8-byte special cases. Updates prefix search block scanning in C/Go/Rust to materialize reconstructed keys before comparison.
KeyKind infrastructure for key representation dispatch
experiments/rust_leaf_bench/matched_go/main.go, experiments/rust_leaf_bench/matched_c/main.c, experiments/rust_leaf_bench/src/main.rs
Introduces KeyKind enum (Bytes vs FixedBe8) and adds key_kind field to Options across implementations. Updates columnar search dispatch in page.searchLeaf to route based on key_kind selection. Wires key_kind into setup functions for different search variants (setupSearchColumnar, setup_search_columnar, etc.).
Variable-length key infrastructure
experiments/rust_leaf_bench/matched_c/main.c, experiments/rust_leaf_bench/matched_go/main.go
Adds VarBytesTable structure in C with per-entry length tracking and offset arrays. Introduces VarSearchCtx for variable-length query contexts. Implements fill_variable_len_key (C) and fillVariableLenKey (Go) generators for deterministic variable-length test keys. Adds setupSearchColumnarVariableLen setup and bench_search_prepared_var benchmark functions for variable-length search benchmarking.
Fixed 8-byte big-endian columnar search optimization
experiments/rust_leaf_bench/matched_c/main.c, experiments/rust_leaf_bench/matched_go/main.go, experiments/rust_leaf_bench/src/main.rs
Adds load_be64_unaligned helper (C) for unaligned 8-byte big-endian reading. Implements search_columnar_v2_fixed_be8 and columnar_fixed_be8_at in C and Rust for direct uint64-based comparisons. Adds searchColumnarV2FixedBE8 in Go with numeric 64-bit ordering. Enables fast path dispatch when key_kind == FixedBe8.
Rust internal storage refactoring
experiments/rust_leaf_bench/src/main.rs
Refactors Builder and Page structures to use fixed-size arena arrays instead of heap-backed Vec fields. Introduces BytesTable and VarBytesTable types with explicit *_len counters for efficient memory layout. Updates make_bench_keys/make_bench_values to return BytesTable. Refactors add_leaf_entry_columnar_v2 and add_leaf_entry_columnar_prefix_v2 to write into fixed arenas. Updates finish_columnar_v2/finish_columnar_prefix_v2 to materialize only initialized entries.
Benchmark orchestration and case integration
experiments/rust_leaf_bench/matched_go/main.go, experiments/rust_leaf_bench/matched_c/main.c, experiments/rust_leaf_bench/src/main.rs, experiments/rust_leaf_bench/run_leaf_smoke.sh
Adds search/columnar_variable_len dispatch case in main() across Go/C/Rust implementations. Calls new setupSearchColumnarVariableLen setup and variable-length benchmark functions. Updates shell script to include search/columnar_variable_len in result ordering and extends awk loop to 8 cases. Changes temp file paths to mktemp-generated names without fixed suffixes.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

Poem

🐰 A leaf-key dance, no more illusions—
Prefix and suffix conjoin without intrusions.
Fixed arrays hum, and variable lengths take flight,
While 8-byte big-endians race through the night.
Virtual helpers fade; reconstruction reigns supreme! ✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.35% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The PR title 'Optimize leaf prefix search benchmarks' is overly broad and vague; it does not clearly specify the main technical change (removing virtual key comparators and reconstructing keys before comparison). Provide a more specific title that describes the core change, such as 'Refactor leaf prefix search to reconstruct keys before comparison' or 'Remove virtual prefix comparator and use direct key comparison'.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/leaf-prefix-search-bench-prod-opt

Comment @coderabbitai help to get the list of available commands and usage tips.

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 optimizes prefix-compressed leaf search by reconstructing fallback keys before comparison and keeps the standalone Go/C/Rust leaf benchmark harnesses aligned with new fixed-BE8 and variable-length search cases.

Changes:

  • Removes the virtual prefix comparator and updates production/matched prefix search paths to compare reconstructed keys.
  • Adds explicit key-kind handling for fixed-BE8 columnar search in benchmark harnesses.
  • Adds variable-length columnar search cases to standalone benchmark outputs and smoke summary.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
TreeDB/node/leaf.go Updates production prefix block search fallback comparison logic.
experiments/rust_leaf_bench/src/main.rs Updates Rust benchmark harness data structures and search cases.
experiments/rust_leaf_bench/run_leaf_smoke.sh Adds variable-length row to smoke benchmark summary.
experiments/rust_leaf_bench/matched_go/main.go Aligns matched Go benchmark search cases and fixed-BE8 handling.
experiments/rust_leaf_bench/matched_c/main.c Aligns matched C benchmark search cases and fixed-BE8 handling.

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

Comment on lines +297 to +306
uint64_t v = 0;
memcpy(&v, src, sizeof(v));
#if defined(__GNUC__) || defined(__clang__)
return __builtin_bswap64(v);
#else
return ((v & 0x00000000000000ffULL) << 56) | ((v & 0x000000000000ff00ULL) << 40) |
((v & 0x0000000000ff0000ULL) << 24) | ((v & 0x00000000ff000000ULL) << 8) |
((v & 0x000000ff00000000ULL) >> 8) | ((v & 0x0000ff0000000000ULL) >> 24) |
((v & 0x00ff000000000000ULL) >> 40) | ((v & 0xff00000000000000ULL) >> 56);
#endif

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@experiments/rust_leaf_bench/matched_c/main.c`:
- Around line 296-307: The function load_be64_unaligned currently always
byte-swaps the copied uint64_t, which breaks correctness on big-endian hosts;
change it to only swap on little-endian systems (leave the value as-is on
big-endian). Locate load_be64_unaligned and after memcpy use a compile-time
endianness check (e.g. __BYTE_ORDER__ / __ORDER_LITTLE_ENDIAN__ or platform
be64toh/be64toh/ntohll if available) to conditionally call __builtin_bswap64(v)
(or equivalent) only when host is little-endian, otherwise return v unchanged so
BE64 values remain correct on big-endian hosts.
🪄 Autofix (Beta)

✅ Autofix completed


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 894d8e11-c186-4117-b893-f94838d2b3f1

📥 Commits

Reviewing files that changed from the base of the PR and between a174be3 and 6370270.

📒 Files selected for processing (5)
  • TreeDB/node/leaf.go
  • experiments/rust_leaf_bench/matched_c/main.c
  • experiments/rust_leaf_bench/matched_go/main.go
  • experiments/rust_leaf_bench/run_leaf_smoke.sh
  • experiments/rust_leaf_bench/src/main.rs

Comment thread experiments/rust_leaf_bench/matched_c/main.c
@coderabbitai

coderabbitai Bot commented May 19, 2026

Copy link
Copy Markdown

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

Fixes Applied Successfully

Fixed 1 file(s) based on 1 unresolved review comment.

Files modified:

  • experiments/rust_leaf_bench/matched_c/main.c

Commit: 4ddce22a46fda8ce6d9064d8e6486cbbc31a2682

The changes have been pushed to the codex/leaf-prefix-search-bench-prod-opt branch.

Time taken: 2m 4s

Fixed 1 file(s) based on 1 unresolved review comment.

Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
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