Skip to content

Commit 22b61d1

Browse files
committed
perf: inline LeafNode::insert logic into insert_into_leaf
- Inline complete leaf insertion logic to eliminate function call overhead - Make insert_at_index public to support inlined implementation - Preserve exact same behavior while improving performance visibility - Prepare for custom memory operation optimizations Performance benefits: - Eliminates leaf.insert() function call overhead - Better compiler optimization opportunities - Single location for optimizing critical insertion path - Foundation for addressing 30% _platform_memmove bottleneck All 300+ tests pass, maintaining full functionality while improving performance characteristics for profiling and optimization.
1 parent a287dc9 commit 22b61d1

2 files changed

Lines changed: 48 additions & 3 deletions

File tree

rust/src/insert_operations.rs

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,53 @@ impl<K: Ord + Clone, V: Clone> BPlusTreeMap<K, V> {
2929

3030
/// Insert into a leaf node by ID.
3131
fn insert_into_leaf(&mut self, leaf_id: NodeId, key: K, value: V) -> InsertResult<K, V> {
32-
self.get_leaf_mut(leaf_id)
33-
.map_or(InsertResult::Updated(None), |leaf| leaf.insert(key, value))
32+
let leaf = match self.get_leaf_mut(leaf_id) {
33+
Some(leaf) => leaf,
34+
None => return InsertResult::Updated(None),
35+
};
36+
37+
// Do binary search once and use the result throughout
38+
match leaf.binary_search_keys(&key) {
39+
Ok(index) => {
40+
// Key already exists, update the value
41+
if let Some(old_val) = leaf.get_value_mut(index) {
42+
let old_value = std::mem::replace(old_val, value);
43+
InsertResult::Updated(Some(old_value))
44+
} else {
45+
InsertResult::Updated(None)
46+
}
47+
}
48+
Err(index) => {
49+
// Key doesn't exist, need to insert
50+
// Check if split is needed BEFORE inserting
51+
if !leaf.is_full() {
52+
// Room to insert without splitting
53+
leaf.insert_at_index(index, key, value);
54+
// Simple insertion - no split needed
55+
return InsertResult::Updated(None);
56+
}
57+
58+
// Node is full, need to split
59+
// Don't insert first. That causes the Vecs to overflow.
60+
// Split the full node
61+
let mut new_right = leaf.split();
62+
// Insert into the correct node
63+
if index <= leaf.keys.len() {
64+
leaf.insert_at_index(index, key, value);
65+
} else {
66+
new_right.insert_at_index(index - leaf.keys.len(), key, value);
67+
}
68+
69+
// Determine the separator key (first key of right node)
70+
let separator_key = new_right.first_key().unwrap().clone();
71+
72+
InsertResult::Split {
73+
old_value: None,
74+
new_node_data: SplitNodeData::Leaf(new_right),
75+
separator_key,
76+
}
77+
}
78+
}
3479
}
3580

3681
/// Recursively insert a key with proper arena access.

rust/src/node.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ impl<K: Ord + Clone, V: Clone> LeafNode<K, V> {
350350
}
351351

352352
/// Insert a key-value pair at the specified index.
353-
fn insert_at_index(&mut self, index: usize, key: K, value: V) {
353+
pub fn insert_at_index(&mut self, index: usize, key: K, value: V) {
354354
self.keys.insert(index, key);
355355
self.values.insert(index, value);
356356
}

0 commit comments

Comments
 (0)