Skip to content

Commit e12f43f

Browse files
authored
feat!: add lazy BTreeMap iterator for improved performance (breaking API change) (#375)
This PR changes the `BTreeMap` iterator's `Item` type from `(K, V)` to `LazyEntry` to enable lazy evaluation of keys and values. This is a **BREAKING API CHANGE**, as it deviates from the canonical `(K, V)` pattern of `std::collections::BTreeMap`. The key motivation is **performance**: previously, each `next()` call eagerly deserialized and cloned key and value, even if the consumer discarded them. With `LazyEntry`, key and value access is deferred until explicitly requested, significantly reducing unnecessary allocations and cloning in cases where only part of the entry is needed or iteration is short-circuited. Code change summary: - Introduced `LazyEntry` with on-demand access to key/value. - Replaced `Box<Node<K>>` with `Rc<Node<K>>` to allow shared ownership between iterator and entries. - Updated all internal iterator consumers to explicitly call `.into_pair()` where eager materialization is needed. Performance change summary: - `BTreeSet`: 68 improvements, no regressions. Median instruction count dropped by **-6.61%**, best case **-17.24%** - `BTreeMap`: 1 small regression (+2.09%), 10 improvements, with up to **-98.33%** fewer instructions in range-heavy cases
1 parent efc567e commit e12f43f

File tree

10 files changed

+504
-395
lines changed

10 files changed

+504
-395
lines changed

benchmarks/btreemap/canbench_results.yml

Lines changed: 207 additions & 207 deletions
Large diffs are not rendered by default.

benchmarks/btreemap/src/main.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -777,7 +777,7 @@ fn range_key_sum_helper_v2(count: usize, size: usize) -> BenchResult {
777777
bench_fn(|| {
778778
btree
779779
.range((Bound::Included(0), Bound::Included(size as u32)))
780-
.map(|(k, _)| k)
780+
.map(|entry| *entry.key())
781781
.sum::<u32>()
782782
})
783783
}
@@ -794,8 +794,8 @@ fn range_value_sum_helper_v2(count: usize, size: usize) -> BenchResult {
794794
bench_fn(|| {
795795
btree
796796
.range((Bound::Included(0), Bound::Included(size as u32)))
797-
.filter(|(k, _)| k % 3 == 0)
798-
.map(|(_, v)| v.len())
797+
.filter(|entry| *entry.key() % 3 == 0)
798+
.map(|entry| entry.value().len())
799799
.sum::<usize>()
800800
})
801801
}

0 commit comments

Comments
 (0)