Skip to content

Conversation

@maksymar
Copy link
Contributor

@maksymar maksymar commented May 21, 2025

This PR enables lazy key loading in BTreeMap for large keys.

Keys larger than a fixed threshold are now loaded lazily, reducing unnecessary memory reads. Smaller keys are still loaded eagerly for performance. After benchmarking various thresholds (4, 8, 16, 32, 64 bytes), 16 bytes was found to offer the best balance between performance and overhead.

image

Detailed benchmark results are available in this CSV report

@github-actions
Copy link

github-actions bot commented May 21, 2025

canbench 🏋 (dir: .) e1fd2d5 2025-05-22 13:03:20 UTC

./canbench_results.yml is up to date
📦 canbench_results_benchmark.csv available in artifacts

---------------------------------------------------

Summary:
  instructions:
    status:   Both improvements and regressions detected! 🟢🔴
    counts:   [total 304 | new 0 | improved 91 | regressed 80 | unchanged 133]
    change:   [min -1.70B | med +160.38K | max +862.12M]
    change %: [min -35.75% | med +0.16% | max +26.12%]

  heap_increase:
    status:   No significant changes detected 👍
    counts:   [total 304 | new 0 | improved 0 | regressed 0 | unchanged 304]
    change:   [min 0 | med 0 | max 0]
    change %: [min 0.00% | med 0.00% | max 0.00%]

  stable_memory_increase:
    status:   No significant changes detected 👍
    counts:   [total 304 | new 0 | improved 0 | regressed 0 | unchanged 304]
    change:   [min 0 | med 0 | max 0]
    change %: [min 0.00% | med 0.00% | max 0.00%]

---------------------------------------------------

Only significant changes:
| status | name                                        |     ins |  ins Δ% | HI |  HI Δ% | SMI |  SMI Δ% |
|--------|---------------------------------------------|---------|---------|----|--------|-----|---------|
|   +    | btreemap_v2_scan_keys_1k_0b                 |   1.18M | +26.12% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreemap_v2_scan_keys_rev_1k_0b             |   1.18M | +25.98% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreemap_v2_remove_blob_1024_128            |   7.42B | +13.16% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreemap_v2_mem_manager_remove_blob512_u64  |   4.41B | +12.69% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreemap_v2_remove_blob_512_128             |   4.12B | +12.29% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreemap_v2_remove_blob_256_128             |   2.46B | +10.45% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreemap_v2_scan_keys_rev_1k_10kib          |   2.57M | +10.27% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreemap_v2_scan_keys_1k_10kib              |   2.59M | +10.13% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreemap_v2_remove_blob_128_128             |   1.63B |  +9.66% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreemap_v2_insert_blob_1024_128            |   5.52B |  +8.17% |  0 |  0.00% | 196 |   0.00% |
|   +    | btreemap_v2_mem_manager_insert_blob512_u64  |   3.19B |  +7.63% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreemap_v2_insert_blob_256_128             |   1.81B |  +7.59% |  0 |  0.00% |  67 |   0.00% |
|   +    | btreemap_v2_insert_blob_512_128             |   3.07B |  +7.34% |  0 |  0.00% | 111 |   0.00% |
|   +    | btreemap_v2_range_count_1k_10kib            |   2.60M |  +6.95% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreemap_v2_remove_blob_32_4                | 725.87M |  +6.32% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreemap_v2_remove_blob_32_8                | 725.88M |  +6.22% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreemap_v2_insert_blob_128_128             |   1.21B |  +6.13% |  0 |  0.00% |  46 |   0.00% |
|   +    | btreemap_v2_remove_blob_32_64               | 767.66M |  +6.11% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreemap_v2_remove_vec_32_8                 | 885.74M |  +6.02% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreemap_v2_insert_blob_32_64               | 553.13M |  +5.99% |  0 |  0.00% |  18 |   0.00% |
|   +    | btreemap_v2_insert_blob_32_32               | 546.88M |  +5.94% |  0 |  0.00% |  13 |   0.00% |
|   +    | btreemap_v2_remove_blob_32_32               | 740.92M |  +5.94% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreemap_v2_remove_vec_32_4                 | 891.61M |  +5.92% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreemap_v2_remove_vec_32_32                | 892.63M |  +5.85% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreemap_v2_insert_blob_32_8                | 535.39M |  +5.83% |  0 |  0.00% |   9 |   0.00% |
|  ...   | ... 121 rows omitted ...                    |         |         |    |        |     |         |
|   -    | btreemap_v2_get_vec_32_256                  | 463.24M | -14.10% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_contains_vec_32_256             | 445.73M | -14.54% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_pop_last_vec_128_128            |   1.55B | -15.37% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_pop_first_vec_128_128           |   1.54B | -15.49% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_insert_vec_1024_128             |   2.79B | -16.00% |  0 |  0.00% | 193 |   0.00% |
|   -    | btreemap_v2_pop_last_vec_256_128            |   2.13B | -17.64% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_pop_first_vec_256_128           |   2.05B | -18.82% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_get_vec_128_128                 | 575.18M | -19.02% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_contains_vec_128_128            | 562.95M | -19.32% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_pop_first_blob_64_128           |   1.07B | -20.66% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_pop_last_blob_64_128            |   1.04B | -21.44% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_pop_last_vec_512_128            |   2.87B | -22.88% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_pop_first_vec_512_128           |   2.75B | -23.57% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_get_vec_256_128                 | 929.71M | -24.59% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_contains_vec_256_128            | 916.95M | -24.83% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_get_blob_64_128                 | 443.02M | -26.75% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_mem_manager_get_vec512_u64      |   1.31B | -26.97% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_mem_manager_contains_vec512_u64 |   1.26B | -27.95% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_contains_blob_64_128            | 419.61M | -28.17% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_pop_last_vec_1024_128           |   4.31B | -28.30% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_pop_first_vec_1024_128          |   4.08B | -29.15% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_get_vec_512_128                 |   1.29B | -29.36% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_contains_vec_512_128            |   1.28B | -29.55% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_get_vec_1024_128                |   1.90B | -35.10% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_contains_vec_1024_128           |   1.85B | -35.75% |  0 |  0.00% |   0 |   0.00% |

---------------------------------------------------
CSV results saved to canbench_results.csv

@maksymar maksymar changed the title feat: add lazy key loading feat: add lazy key loading for BTreeMap May 21, 2025
@maksymar maksymar requested a review from Copilot May 21, 2025 18:54
Copy link
Contributor

Copilot AI left a comment

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 lazy key loading for BTreeMap nodes by eagerly loading keys when their size is small and deferring loading for larger keys. Key changes include updating node implementations in both V1 and V2, refactoring public APIs to pass memory context, and introducing a LazyKey type to encapsulate lazy key behavior.

Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/btreemap/node/v2.rs Eagerly loads small keys using a threshold while deferring large ones.
src/btreemap/node/v1.rs Updates key/value loading to use lazy references and adjusts offsets.
src/btreemap/node.rs Refactors key handling with LazyKey and propagates memory parameters.
src/btreemap/iter.rs Updates iterator methods to include memory context in key retrieval.
src/btreemap.rs Propagates memory context across search and insertion operations.
Comments suppressed due to low confidence (1)

src/btreemap/node/v2.rs:170

  • When eagerly loading small keys, the same mutable buffer 'buf' is reused across iterations. If K::from_bytes does not clone the key bytes, this may lead to data corruption in subsequent iterations. Consider cloning the loaded bytes or allocating a new buffer for each key.
read_to_vec(&reader, Address::from(offset.get()), &mut buf, key_size as usize);

@maksymar maksymar marked this pull request as ready for review May 21, 2025 18:59
@maksymar maksymar requested a review from a team as a code owner May 21, 2025 18:59
@maksymar maksymar requested a review from dsarlis May 21, 2025 19:00
@maksymar maksymar changed the title feat: add lazy key loading for BTreeMap feat: add lazy key loading for large BTreeMap keys May 21, 2025
@maksymar maksymar changed the title feat: add lazy key loading for large BTreeMap keys feat: add lazy loading for large BTreeMap keys May 21, 2025
Copy link
Member

@dsarlis dsarlis left a comment

Choose a reason for hiding this comment

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

Lgtm!

@maksymar maksymar merged commit d1f2670 into main May 22, 2025
10 checks passed
@maksymar maksymar deleted the maksym/lazy-keys-3 branch May 22, 2025 15:04
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