From 0de3320eeb0ac2c0551d9241a66d7e30a9174675 Mon Sep 17 00:00:00 2001 From: Vladimir Petrzhikovskii Date: Sat, 12 Oct 2024 11:14:46 +0200 Subject: [PATCH] perf: remove reallocations in compute hashes --- src/cell/cell_context.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/cell/cell_context.rs b/src/cell/cell_context.rs index ab28df33..8044dc8f 100644 --- a/src/cell/cell_context.rs +++ b/src/cell/cell_context.rs @@ -89,9 +89,6 @@ impl<'a> CellParts<'a> { let references = self.references.as_ref(); - // `hashes_len` is guaranteed to be in range 1..4 - let mut hashes_len = level + 1; - let (cell_type, computed_level_mask) = if unlikely(descriptor.is_exotic()) { let Some(&first_byte) = self.data.first() else { return Err(Error::InvalidCell); @@ -114,7 +111,6 @@ impl<'a> CellParts<'a> { return Err(Error::InvalidCell); } - hashes_len = 1; (CellType::PrunedBranch, level_mask) } // 8 bits type, hash, depth @@ -157,7 +153,19 @@ impl<'a> CellParts<'a> { let level_offset = cell_type.is_merkle() as u8; let is_pruned = cell_type.is_pruned_branch(); - let mut hashes = Vec::<(HashBytes, u16)>::with_capacity(hashes_len); + // this calculation mimics the underlying loop to avoid reallocations + let mut hashes = { + let mut hashes_len = 0; + for lvl in 0..4 { + // Skip non-zero levels for pruned branches and insignificant hashes for other cells + if lvl != 0 && (is_pruned || !level_mask.contains(lvl)) { + continue; + } + hashes_len += 1; + } + Vec::<(HashBytes, u16)>::with_capacity(hashes_len) + }; + for level in 0..4 { // Skip non-zero levels for pruned branches and insignificant hashes for other cells if level != 0 && (is_pruned || !level_mask.contains(level)) {