From a862edfe194cfb9e0c30073ae095227fb280bdf0 Mon Sep 17 00:00:00 2001 From: Hamish Peebles Date: Wed, 16 Oct 2024 17:03:55 +0100 Subject: [PATCH 1/7] feat: move initialization of `StableBTreeMap` cursors into `Iter` --- src/btreemap.rs | 124 ++++++------------------------------------- src/btreemap/iter.rs | 114 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 123 insertions(+), 115 deletions(-) diff --git a/src/btreemap.rs b/src/btreemap.rs index 716eaf77..02364e75 100644 --- a/src/btreemap.rs +++ b/src/btreemap.rs @@ -1023,107 +1023,25 @@ where key_range.end_bound().cloned(), ); - let mut cursors = vec![]; - - match key_range.start_bound() { - Bound::Unbounded => { - cursors.push(Cursor::Address(self.root_addr)); - Iter::new_in_range(self, range, cursors) - } - Bound::Included(key) | Bound::Excluded(key) => { - let mut node = self.load_node(self.root_addr); - loop { - match node.search(key) { - Ok(idx) => { - if let Bound::Included(_) = key_range.start_bound() { - // We found the key exactly matching the left bound. - // Here is where we'll start the iteration. - cursors.push(Cursor::Node { - node, - next: Index::Entry(idx), - }); - return Iter::new_in_range(self, range, cursors); - } else { - // We found the key that we must - // exclude. We add its right neighbor - // to the stack and start iterating - // from its right child. - let right_child = match node.node_type() { - NodeType::Internal => Some(node.child(idx + 1)), - NodeType::Leaf => None, - }; - - if idx + 1 != node.entries_len() - && key_range.contains(node.key(idx + 1)) - { - cursors.push(Cursor::Node { - node, - next: Index::Entry(idx + 1), - }); - } - if let Some(right_child) = right_child { - cursors.push(Cursor::Address(right_child)); - } - return Iter::new_in_range(self, range, cursors); - } - } - Err(idx) => { - // The `idx` variable points to the first - // key that is greater than the left - // bound. - // - // If the index points to a valid node, we - // will visit its left subtree and then - // return to this key. - // - // If the index points at the end of - // array, we'll continue with the right - // child of the last key. - - // Load the left child of the node to visit if it exists. - // This is done first to avoid cloning the node. - let child = match node.node_type() { - NodeType::Internal => { - // Note that loading a child node cannot fail since - // len(children) = len(entries) + 1 - Some(self.load_node(node.child(idx))) - } - NodeType::Leaf => None, - }; - - if idx < node.entries_len() && key_range.contains(node.key(idx)) { - cursors.push(Cursor::Node { - node, - next: Index::Entry(idx), - }); - } - - match child { - None => { - // Leaf node. Return an iterator with the found cursors. - return Iter::new_in_range(self, range, cursors); - } - Some(child) => { - // Iterate over the child node. - node = child; - } - } - } - } - } - } - } + Iter::new_in_range(self, range) } /// Returns an iterator pointing to the first element below the given bound. /// Returns an empty iterator if there are no keys below the given bound. pub fn iter_upper_bound(&self, bound: &K) -> Iter { + if let Some(key) = self.find_by_upper_bound(bound) { + Iter::new_in_range(self, (Bound::Included(key), Bound::Unbounded)) + } else { + Iter::null(self) + } + } + + fn find_by_upper_bound(&self, bound: &K) -> Option { if self.root_addr == NULL { // Map is empty. - return Iter::null(self); + return None; } - let dummy_bounds = (Bound::Unbounded, Bound::Unbounded); // INVARIANT: all cursors point to keys greater than or equal to bound. let mut cursors = vec![]; @@ -1149,27 +1067,19 @@ where debug_assert!(node.key(n) >= bound); continue; } else { - debug_assert!(node.key(n - 1) < bound); - cursors.push(Cursor::Node { - node, - next: Index::Entry(n - 1), - }); - break; + let key: &K = node.key(n - 1); + debug_assert!(key < bound); + return Some(key.clone()); } } _ => panic!("BUG: unexpected cursor shape"), } } - // If the cursors are empty, the iterator will be empty. - return Iter::new_in_range(self, dummy_bounds, cursors); + return None; } - debug_assert!(node.key(idx - 1) < bound); - - cursors.push(Cursor::Node { - node, - next: Index::Entry(idx - 1), - }); - return Iter::new_in_range(self, dummy_bounds, cursors); + let key = node.key(idx - 1); + debug_assert!(key < bound); + return Some(key.clone()); } NodeType::Internal => { let child = self.load_node(node.child(idx)); diff --git a/src/btreemap/iter.rs b/src/btreemap/iter.rs index 3949352f..5ca4ea61 100644 --- a/src/btreemap/iter.rs +++ b/src/btreemap/iter.rs @@ -29,6 +29,9 @@ where // A reference to the map being iterated on. map: &'a BTreeMap, + // A flag indicating if the cursors have been initialized yet. + cursors_initialized: bool, + // A stack of cursors indicating the current position in the tree. cursors: Vec>, @@ -45,8 +48,8 @@ where pub(crate) fn new(map: &'a BTreeMap) -> Self { Self { map, - // Initialize the cursors with the address of the root of the map. - cursors: vec![Cursor::Address(map.root_addr)], + cursors_initialized: false, + cursors: vec![], range: (Bound::Unbounded, Bound::Unbounded), } } @@ -55,26 +58,121 @@ where pub(crate) fn null(map: &'a BTreeMap) -> Self { Self { map, + cursors_initialized: true, cursors: vec![], range: (Bound::Unbounded, Bound::Unbounded), } } - pub(crate) fn new_in_range( - map: &'a BTreeMap, - range: (Bound, Bound), - cursors: Vec>, - ) -> Self { + pub(crate) fn new_in_range(map: &'a BTreeMap, range: (Bound, Bound)) -> Self { Self { map, - cursors, + cursors_initialized: false, + cursors: vec![], range, } } + fn ensure_cursors_initialized(&mut self) { + if self.cursors_initialized { + return; + } + + match self.range.start_bound() { + Bound::Unbounded => { + self.cursors.push(Cursor::Address(self.map.root_addr)); + } + Bound::Included(key) | Bound::Excluded(key) => { + let mut node = self.map.load_node(self.map.root_addr); + loop { + match node.search(key) { + Ok(idx) => { + if let Bound::Included(_) = self.range.start_bound() { + // We found the key exactly matching the left bound. + // Here is where we'll start the iteration. + self.cursors.push(Cursor::Node { + node, + next: Index::Entry(idx), + }); + break; + } else { + // We found the key that we must + // exclude. We add its right neighbor + // to the stack and start iterating + // from its right child. + let right_child = match node.node_type() { + NodeType::Internal => Some(node.child(idx + 1)), + NodeType::Leaf => None, + }; + + if idx + 1 != node.entries_len() + && self.range.contains(node.key(idx + 1)) + { + self.cursors.push(Cursor::Node { + node, + next: Index::Entry(idx + 1), + }); + } + if let Some(right_child) = right_child { + self.cursors.push(Cursor::Address(right_child)); + } + break; + } + } + Err(idx) => { + // The `idx` variable points to the first + // key that is greater than the left + // bound. + // + // If the index points to a valid node, we + // will visit its left subtree and then + // return to this key. + // + // If the index points at the end of + // array, we'll continue with the right + // child of the last key. + + // Load the left child of the node to visit if it exists. + // This is done first to avoid cloning the node. + let child = match node.node_type() { + NodeType::Internal => { + // Note that loading a child node cannot fail since + // len(children) = len(entries) + 1 + Some(self.map.load_node(node.child(idx))) + } + NodeType::Leaf => None, + }; + + if idx < node.entries_len() && self.range.contains(node.key(idx)) { + self.cursors.push(Cursor::Node { + node, + next: Index::Entry(idx), + }); + } + + match child { + None => { + // Leaf node. Return an iterator with the found cursors. + break; + } + Some(child) => { + // Iterate over the child node. + node = child; + } + } + } + } + } + } + } + self.cursors_initialized = true; + } + // Iterates to find the next element in the requested range. // If it exists, `map` is applied to that element and the result is returned. fn next_map, usize) -> T>(&mut self, map: F) -> Option { + self.ensure_cursors_initialized(); + // If the cursors are empty. Iteration is complete. match self.cursors.pop()? { Cursor::Address(address) => { From a720764475034b2f44a900abf1454552050dfc94 Mon Sep 17 00:00:00 2001 From: Hamish Peebles Date: Wed, 16 Oct 2024 17:17:50 +0100 Subject: [PATCH 2/7] Add `new_with_cursors` ctor --- src/btreemap.rs | 53 ++++++++++++++++++++++---------------------- src/btreemap/iter.rs | 9 ++++++++ 2 files changed, 36 insertions(+), 26 deletions(-) diff --git a/src/btreemap.rs b/src/btreemap.rs index 02364e75..5c787ba1 100644 --- a/src/btreemap.rs +++ b/src/btreemap.rs @@ -1029,19 +1029,12 @@ where /// Returns an iterator pointing to the first element below the given bound. /// Returns an empty iterator if there are no keys below the given bound. pub fn iter_upper_bound(&self, bound: &K) -> Iter { - if let Some(key) = self.find_by_upper_bound(bound) { - Iter::new_in_range(self, (Bound::Included(key), Bound::Unbounded)) - } else { - Iter::null(self) - } - } - - fn find_by_upper_bound(&self, bound: &K) -> Option { if self.root_addr == NULL { // Map is empty. - return None; + return Iter::null(self); } + let dummy_bounds = (Bound::Unbounded, Bound::Unbounded); // INVARIANT: all cursors point to keys greater than or equal to bound. let mut cursors = vec![]; @@ -1067,19 +1060,27 @@ where debug_assert!(node.key(n) >= bound); continue; } else { - let key: &K = node.key(n - 1); - debug_assert!(key < bound); - return Some(key.clone()); + debug_assert!(node.key(n - 1) < bound); + cursors.push(Cursor::Node { + node, + next: Index::Entry(n - 1), + }); + break; } } _ => panic!("BUG: unexpected cursor shape"), } } - return None; + // If the cursors are empty, the iterator will be empty. + return Iter::new_with_cursors(self, dummy_bounds, cursors); } - let key = node.key(idx - 1); - debug_assert!(key < bound); - return Some(key.clone()); + debug_assert!(node.key(idx - 1) < bound); + + cursors.push(Cursor::Node { + node, + next: Index::Entry(idx - 1), + }); + return Iter::new_with_cursors(self, dummy_bounds, cursors); } NodeType::Internal => { let child = self.load_node(node.child(idx)); @@ -1145,13 +1146,13 @@ where buf[0..3].copy_from_slice(MAGIC.as_slice()); match header.version { Version::V1(DerivedPageSize { - max_key_size, - max_value_size, - }) + max_key_size, + max_value_size, + }) | Version::V2(PageSize::Derived(DerivedPageSize { - max_key_size, - max_value_size, - })) => { + max_key_size, + max_value_size, + })) => { buf[3] = LAYOUT_VERSION; buf[4..8].copy_from_slice(&max_key_size.to_le_bytes()); buf[8..12].copy_from_slice(&max_value_size.to_le_bytes()); @@ -2505,7 +2506,7 @@ mod test { // Tests an offset that has a keys somewhere in the range of keys of an internal node. assert_eq!( btree.range(b(&[1, 3])..b(&[2])).collect::>(), - vec![(b(&[1, 3]), b(&[])), (b(&[1, 4]), b(&[])),] + vec![(b(&[1, 3]), b(&[])), (b(&[1, 4]), b(&[])), ] ); // Tests an offset that's larger than the key in the internal node. @@ -2882,9 +2883,9 @@ mod test { assert!(packed_header.version == LAYOUT_VERSION); match v1_header.version { Version::V1(DerivedPageSize { - max_key_size, - max_value_size, - }) => { + max_key_size, + max_value_size, + }) => { assert!(packed_header.max_key_size == max_key_size); assert!(packed_header.max_value_size == max_value_size); } diff --git a/src/btreemap/iter.rs b/src/btreemap/iter.rs index 5ca4ea61..b9b9cff9 100644 --- a/src/btreemap/iter.rs +++ b/src/btreemap/iter.rs @@ -73,6 +73,15 @@ where } } + pub(crate) fn new_with_cursors(map: &'a BTreeMap, range: (Bound, Bound), cursors: Vec>) -> Self { + Self { + map, + cursors_initialized: true, + cursors, + range, + } + } + fn ensure_cursors_initialized(&mut self) { if self.cursors_initialized { return; From d2306c084e8b87216e290002bf314cc460b169e0 Mon Sep 17 00:00:00 2001 From: Hamish Peebles Date: Wed, 16 Oct 2024 17:19:24 +0100 Subject: [PATCH 3/7] Not sure why the formatting went weird there --- src/btreemap.rs | 20 ++++++++++---------- src/btreemap/iter.rs | 6 +++++- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/btreemap.rs b/src/btreemap.rs index 5c787ba1..47c6ab58 100644 --- a/src/btreemap.rs +++ b/src/btreemap.rs @@ -1146,13 +1146,13 @@ where buf[0..3].copy_from_slice(MAGIC.as_slice()); match header.version { Version::V1(DerivedPageSize { - max_key_size, - max_value_size, - }) + max_key_size, + max_value_size, + }) | Version::V2(PageSize::Derived(DerivedPageSize { - max_key_size, - max_value_size, - })) => { + max_key_size, + max_value_size, + })) => { buf[3] = LAYOUT_VERSION; buf[4..8].copy_from_slice(&max_key_size.to_le_bytes()); buf[8..12].copy_from_slice(&max_value_size.to_le_bytes()); @@ -2506,7 +2506,7 @@ mod test { // Tests an offset that has a keys somewhere in the range of keys of an internal node. assert_eq!( btree.range(b(&[1, 3])..b(&[2])).collect::>(), - vec![(b(&[1, 3]), b(&[])), (b(&[1, 4]), b(&[])), ] + vec![(b(&[1, 3]), b(&[])), (b(&[1, 4]), b(&[])),] ); // Tests an offset that's larger than the key in the internal node. @@ -2883,9 +2883,9 @@ mod test { assert!(packed_header.version == LAYOUT_VERSION); match v1_header.version { Version::V1(DerivedPageSize { - max_key_size, - max_value_size, - }) => { + max_key_size, + max_value_size, + }) => { assert!(packed_header.max_key_size == max_key_size); assert!(packed_header.max_value_size == max_value_size); } diff --git a/src/btreemap/iter.rs b/src/btreemap/iter.rs index b9b9cff9..0ec08de1 100644 --- a/src/btreemap/iter.rs +++ b/src/btreemap/iter.rs @@ -73,7 +73,11 @@ where } } - pub(crate) fn new_with_cursors(map: &'a BTreeMap, range: (Bound, Bound), cursors: Vec>) -> Self { + pub(crate) fn new_with_cursors( + map: &'a BTreeMap, + range: (Bound, Bound), + cursors: Vec>, + ) -> Self { Self { map, cursors_initialized: true, From 03d78a8646f3c9e5becc3cbd9a240f095de801ee Mon Sep 17 00:00:00 2001 From: Hamish Peebles Date: Wed, 16 Oct 2024 17:29:52 +0100 Subject: [PATCH 4/7] Add comment --- src/btreemap/iter.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/btreemap/iter.rs b/src/btreemap/iter.rs index 0ec08de1..9fd03f32 100644 --- a/src/btreemap/iter.rs +++ b/src/btreemap/iter.rs @@ -73,6 +73,7 @@ where } } + // This can be used as an optimisation if the cursors have already been calculated pub(crate) fn new_with_cursors( map: &'a BTreeMap, range: (Bound, Bound), From db8a1976a28c34cd15381c060cad0875e549a93c Mon Sep 17 00:00:00 2001 From: Hamish Peebles Date: Thu, 17 Oct 2024 09:31:05 +0100 Subject: [PATCH 5/7] Tiny speedup --- src/btreemap/iter.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/btreemap/iter.rs b/src/btreemap/iter.rs index 9fd03f32..f8b73a6a 100644 --- a/src/btreemap/iter.rs +++ b/src/btreemap/iter.rs @@ -87,10 +87,8 @@ where } } - fn ensure_cursors_initialized(&mut self) { - if self.cursors_initialized { - return; - } + fn initialize_cursors(&mut self) { + debug_assert!(!self.cursors_initialized); match self.range.start_bound() { Bound::Unbounded => { @@ -185,7 +183,9 @@ where // Iterates to find the next element in the requested range. // If it exists, `map` is applied to that element and the result is returned. fn next_map, usize) -> T>(&mut self, map: F) -> Option { - self.ensure_cursors_initialized(); + if !self.cursors_initialized { + self.initialize_cursors(); + } // If the cursors are empty. Iteration is complete. match self.cursors.pop()? { From b38d79d59327735d493f8d03db976be3bf29ad31 Mon Sep 17 00:00:00 2001 From: Hamish Peebles Date: Fri, 25 Oct 2024 15:15:16 +0100 Subject: [PATCH 6/7] Add comment --- src/btreemap/iter.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/btreemap/iter.rs b/src/btreemap/iter.rs index f8b73a6a..2492aca7 100644 --- a/src/btreemap/iter.rs +++ b/src/btreemap/iter.rs @@ -29,7 +29,9 @@ where // A reference to the map being iterated on. map: &'a BTreeMap, - // A flag indicating if the cursors have been initialized yet. + // A flag indicating if the cursors have been initialized yet. This is needed to distinguish + // between the case where the iteration hasn't started yet and the case where the iteration has + // finished (in both cases the `cursors` field will be empty). cursors_initialized: bool, // A stack of cursors indicating the current position in the tree. From b323b0af18b1fdba5820c374a65876e16e78ac11 Mon Sep 17 00:00:00 2001 From: Hamish Peebles Date: Tue, 5 Nov 2024 22:33:09 +0000 Subject: [PATCH 7/7] Update canbench results --- canbench_results.yml | 130 +++++++++++++++++++++---------------------- 1 file changed, 65 insertions(+), 65 deletions(-) diff --git a/canbench_results.yml b/canbench_results.yml index 76f2bee3..62a7066d 100644 --- a/canbench_results.yml +++ b/canbench_results.yml @@ -133,379 +133,379 @@ benches: scopes: {} btreemap_insert_10mib_values: total: - instructions: 145812477 + instructions: 145922325 heap_increase: 0 stable_memory_increase: 32 scopes: {} btreemap_insert_blob_1024_128: total: - instructions: 5161897359 + instructions: 5161914701 heap_increase: 0 stable_memory_increase: 262 scopes: {} btreemap_insert_blob_1024_128_v2: total: - instructions: 5551050739 + instructions: 5551068081 heap_increase: 0 stable_memory_increase: 196 scopes: {} btreemap_insert_blob_1024_16: total: - instructions: 5117351375 + instructions: 5117369042 heap_increase: 0 stable_memory_increase: 241 scopes: {} btreemap_insert_blob_1024_16_v2: total: - instructions: 5508484410 + instructions: 5508502115 heap_increase: 0 stable_memory_increase: 181 scopes: {} btreemap_insert_blob_1024_256: total: - instructions: 5184887283 + instructions: 5184904755 heap_increase: 0 stable_memory_increase: 292 scopes: {} btreemap_insert_blob_1024_256_v2: total: - instructions: 5574297530 + instructions: 5574315002 heap_increase: 0 stable_memory_increase: 219 scopes: {} btreemap_insert_blob_1024_32: total: - instructions: 5124591897 + instructions: 5124609174 heap_increase: 0 stable_memory_increase: 239 scopes: {} btreemap_insert_blob_1024_32_v2: total: - instructions: 5514794407 + instructions: 5514811773 heap_increase: 0 stable_memory_increase: 180 scopes: {} btreemap_insert_blob_1024_4: total: - instructions: 5013226971 + instructions: 5013244404 heap_increase: 0 stable_memory_increase: 235 scopes: {} btreemap_insert_blob_1024_4_v2: total: - instructions: 5408556192 + instructions: 5408573739 heap_increase: 0 stable_memory_increase: 176 scopes: {} btreemap_insert_blob_1024_512: total: - instructions: 5296477642 + instructions: 5296495023 heap_increase: 0 stable_memory_increase: 348 scopes: {} btreemap_insert_blob_1024_512_v2: total: - instructions: 5692592790 + instructions: 5692610171 heap_increase: 0 stable_memory_increase: 261 scopes: {} btreemap_insert_blob_1024_64: total: - instructions: 5160666685 + instructions: 5160684248 heap_increase: 0 stable_memory_increase: 250 scopes: {} btreemap_insert_blob_1024_64_v2: total: - instructions: 5550334403 + instructions: 5550351966 heap_increase: 0 stable_memory_increase: 188 scopes: {} btreemap_insert_blob_1024_8: total: - instructions: 5098581170 + instructions: 5098598668 heap_increase: 0 stable_memory_increase: 237 scopes: {} btreemap_insert_blob_1024_8_v2: total: - instructions: 5491442141 + instructions: 5491459791 heap_increase: 0 stable_memory_increase: 178 scopes: {} btreemap_insert_blob_128_1024: total: - instructions: 1521313518 + instructions: 1521330782 heap_increase: 0 stable_memory_increase: 260 scopes: {} btreemap_insert_blob_128_1024_v2: total: - instructions: 1651648946 + instructions: 1651666210 heap_increase: 0 stable_memory_increase: 195 scopes: {} btreemap_insert_blob_16_1024: total: - instructions: 914649153 + instructions: 914664896 heap_increase: 0 stable_memory_increase: 215 scopes: {} btreemap_insert_blob_16_1024_v2: total: - instructions: 1012886554 + instructions: 1012902411 heap_increase: 0 stable_memory_increase: 161 scopes: {} btreemap_insert_blob_256_1024: total: - instructions: 2072274900 + instructions: 2072292372 heap_increase: 0 stable_memory_increase: 292 scopes: {} btreemap_insert_blob_256_1024_v2: total: - instructions: 2262444663 + instructions: 2262462135 heap_increase: 0 stable_memory_increase: 219 scopes: {} btreemap_insert_blob_32_1024: total: - instructions: 971181545 + instructions: 971198185 heap_increase: 0 stable_memory_increase: 230 scopes: {} btreemap_insert_blob_32_1024_v2: total: - instructions: 1063753591 + instructions: 1063770231 heap_increase: 0 stable_memory_increase: 173 scopes: {} btreemap_insert_blob_4_1024: total: - instructions: 702280030 + instructions: 702289156 heap_increase: 0 stable_memory_increase: 123 scopes: {} btreemap_insert_blob_4_1024_v2: total: - instructions: 787268408 + instructions: 787277534 heap_increase: 0 stable_memory_increase: 92 scopes: {} btreemap_insert_blob_512_1024: total: - instructions: 3204802664 + instructions: 3204820188 heap_increase: 0 stable_memory_increase: 351 scopes: {} btreemap_insert_blob_512_1024_v2: total: - instructions: 3464684781 + instructions: 3464702305 heap_increase: 0 stable_memory_increase: 263 scopes: {} btreemap_insert_blob_64_1024: total: - instructions: 1242001761 + instructions: 1242018908 heap_increase: 0 stable_memory_increase: 245 scopes: {} btreemap_insert_blob_64_1024_v2: total: - instructions: 1345180958 + instructions: 1345198105 heap_increase: 0 stable_memory_increase: 183 scopes: {} btreemap_insert_blob_8_1024: total: - instructions: 828098541 + instructions: 828112100 heap_increase: 0 stable_memory_increase: 183 scopes: {} btreemap_insert_blob_8_1024_v2: total: - instructions: 919884588 + instructions: 919898223 heap_increase: 0 stable_memory_increase: 138 scopes: {} btreemap_insert_blob_8_u64: total: - instructions: 424320990 + instructions: 424334575 heap_increase: 0 stable_memory_increase: 6 scopes: {} btreemap_insert_blob_8_u64_v2: total: - instructions: 524532367 + instructions: 524551164 heap_increase: 0 stable_memory_increase: 4 scopes: {} btreemap_insert_u64_blob_8: total: - instructions: 435841221 + instructions: 435858693 heap_increase: 0 stable_memory_increase: 7 scopes: {} btreemap_insert_u64_blob_8_v2: total: - instructions: 502367747 + instructions: 502390007 heap_increase: 0 stable_memory_increase: 5 scopes: {} btreemap_insert_u64_u64: total: - instructions: 448311336 + instructions: 448328834 heap_increase: 0 stable_memory_increase: 7 scopes: {} btreemap_insert_u64_u64_v2: total: - instructions: 518585831 + instructions: 518609796 heap_increase: 0 stable_memory_increase: 6 scopes: {} btreemap_iter_count_10mib_values: total: - instructions: 521270 + instructions: 525036 heap_increase: 0 stable_memory_increase: 0 scopes: {} btreemap_iter_count_small_values: total: - instructions: 10242765 + instructions: 10458516 heap_increase: 0 stable_memory_increase: 0 scopes: {} btreemap_remove_blob_128_1024: total: - instructions: 1916023862 + instructions: 1916049094 heap_increase: 0 stable_memory_increase: 0 scopes: {} btreemap_remove_blob_128_1024_v2: total: - instructions: 2060123740 + instructions: 2060148972 heap_increase: 0 stable_memory_increase: 0 scopes: {} btreemap_remove_blob_16_1024: total: - instructions: 1174997981 + instructions: 1175020990 heap_increase: 0 stable_memory_increase: 0 scopes: {} btreemap_remove_blob_16_1024_v2: total: - instructions: 1310740941 + instructions: 1310763950 heap_increase: 0 stable_memory_increase: 0 scopes: {} btreemap_remove_blob_256_1024: total: - instructions: 2563712145 + instructions: 2563737681 heap_increase: 0 stable_memory_increase: 0 scopes: {} btreemap_remove_blob_256_1024_v2: total: - instructions: 2714997748 + instructions: 2715023284 heap_increase: 0 stable_memory_increase: 0 scopes: {} btreemap_remove_blob_32_1024: total: - instructions: 1257954087 + instructions: 1257978407 heap_increase: 0 stable_memory_increase: 0 scopes: {} btreemap_remove_blob_32_1024_v2: total: - instructions: 1396007710 + instructions: 1396032068 heap_increase: 0 stable_memory_increase: 0 scopes: {} btreemap_remove_blob_4_1024: total: - instructions: 730539960 + instructions: 730553298 heap_increase: 0 stable_memory_increase: 0 scopes: {} btreemap_remove_blob_4_1024_v2: total: - instructions: 832319712 + instructions: 832333088 heap_increase: 0 stable_memory_increase: 0 scopes: {} btreemap_remove_blob_512_1024: total: - instructions: 3925463425 + instructions: 3925489037 heap_increase: 0 stable_memory_increase: 0 scopes: {} btreemap_remove_blob_512_1024_v2: total: - instructions: 4079794221 + instructions: 4079819871 heap_increase: 0 stable_memory_increase: 0 scopes: {} btreemap_remove_blob_64_1024: total: - instructions: 1579833528 + instructions: 1579858589 heap_increase: 0 stable_memory_increase: 0 scopes: {} btreemap_remove_blob_64_1024_v2: total: - instructions: 1719825276 + instructions: 1719850337 heap_increase: 0 stable_memory_increase: 0 scopes: {} btreemap_remove_blob_8_1024: total: - instructions: 958306352 + instructions: 958326169 heap_increase: 0 stable_memory_increase: 0 scopes: {} btreemap_remove_blob_8_1024_v2: total: - instructions: 1076045855 + instructions: 1076065710 heap_increase: 0 stable_memory_increase: 0 scopes: {} btreemap_remove_blob_8_u64: total: - instructions: 549451611 + instructions: 549471466 heap_increase: 0 stable_memory_increase: 0 scopes: {} btreemap_remove_blob_8_u64_v2: total: - instructions: 685586627 + instructions: 685613050 heap_increase: 0 stable_memory_increase: 0 scopes: {} btreemap_remove_u64_blob_8: total: - instructions: 609355138 + instructions: 609380674 heap_increase: 0 stable_memory_increase: 0 scopes: {} btreemap_remove_u64_blob_8_v2: total: - instructions: 705661181 + instructions: 705692037 heap_increase: 0 stable_memory_increase: 0 scopes: {} btreemap_remove_u64_u64: total: - instructions: 634545364 + instructions: 634570938 heap_increase: 0 stable_memory_increase: 0 scopes: {} btreemap_remove_u64_u64_v2: total: - instructions: 739907256 + instructions: 739939423 heap_increase: 0 stable_memory_increase: 0 scopes: {} @@ -517,13 +517,13 @@ benches: scopes: {} memory_manager_grow: total: - instructions: 352839872 + instructions: 351687872 heap_increase: 2 stable_memory_increase: 32000 scopes: {} memory_manager_overhead: total: - instructions: 1182161127 + instructions: 1182143127 heap_increase: 0 stable_memory_increase: 8320 scopes: {}