From c0fc4b4a3add8559063cf3eb4a15064380cb3997 Mon Sep 17 00:00:00 2001 From: Nicole Date: Thu, 23 Apr 2026 17:15:41 -0300 Subject: [PATCH] skip Rayon on Merkle tree levels with fewer than 1024 nodes --- crypto/crypto/src/merkle_tree/traits.rs | 17 ++++++++---- crypto/crypto/src/merkle_tree/utils.rs | 37 +++++++++++++++++++------ 2 files changed, 40 insertions(+), 14 deletions(-) diff --git a/crypto/crypto/src/merkle_tree/traits.rs b/crypto/crypto/src/merkle_tree/traits.rs index c09cff9d0..81665278b 100644 --- a/crypto/crypto/src/merkle_tree/traits.rs +++ b/crypto/crypto/src/merkle_tree/traits.rs @@ -16,11 +16,18 @@ pub trait IsMerkleTreeBackend { /// tree will be built from and converts it to a list of leaf nodes. fn hash_leaves(unhashed_leaves: &[Self::Data]) -> Vec { #[cfg(feature = "parallel")] - let iter = unhashed_leaves.par_iter(); - #[cfg(not(feature = "parallel"))] - let iter = unhashed_leaves.iter(); - - iter.map(|leaf| Self::hash_data(leaf)).collect() + { + if unhashed_leaves.len() >= 1024 { + return unhashed_leaves + .par_iter() + .map(|leaf| Self::hash_data(leaf)) + .collect(); + } + } + unhashed_leaves + .iter() + .map(|leaf| Self::hash_data(leaf)) + .collect() } /// This function takes to children nodes and builds a new parent node. diff --git a/crypto/crypto/src/merkle_tree/utils.rs b/crypto/crypto/src/merkle_tree/utils.rs index 7cc64166b..bd971bb9c 100644 --- a/crypto/crypto/src/merkle_tree/utils.rs +++ b/crypto/crypto/src/merkle_tree/utils.rs @@ -78,17 +78,36 @@ where let (new_level_iter, children_iter) = nodes[new_level_begin_index..level_end_index + 1].split_at_mut(new_level_length); + // Skip Rayon for small levels: the scheduling overhead exceeds + // computation for levels with fewer than 1024 nodes. This avoids + // hundreds of unnecessary task spawns from small FRI layer trees. #[cfg(feature = "parallel")] - let parent_and_children_zipped_iter = new_level_iter - .into_par_iter() - .zip(children_iter.par_chunks_exact(2)); + { + if new_level_length >= 1024 { + new_level_iter + .into_par_iter() + .zip(children_iter.par_chunks_exact(2)) + .for_each(|(new_parent, children)| { + *new_parent = B::hash_new_parent(&children[0], &children[1]); + }); + } else { + new_level_iter + .iter_mut() + .zip(children_iter.chunks_exact(2)) + .for_each(|(new_parent, children)| { + *new_parent = B::hash_new_parent(&children[0], &children[1]); + }); + } + } #[cfg(not(feature = "parallel"))] - let parent_and_children_zipped_iter = - new_level_iter.iter_mut().zip(children_iter.chunks_exact(2)); - - parent_and_children_zipped_iter.for_each(|(new_parent, children)| { - *new_parent = B::hash_new_parent(&children[0], &children[1]); - }); + { + new_level_iter + .iter_mut() + .zip(children_iter.chunks_exact(2)) + .for_each(|(new_parent, children)| { + *new_parent = B::hash_new_parent(&children[0], &children[1]); + }); + } level_end_index = level_begin_index - 1; level_begin_index = new_level_begin_index;