pub fn compute_merkle_root_loop<T, F>(hashes: Vec<T>, fanout: usize, extractor: F) -> Hash
    where
        F: Fn(&T) -> Hash + std::marker::Sync,
        T: std::marker::Sync,
    {
        if hashes.is_empty() {
            return Hasher::default().result();
        }

        let mut time = Measure::start("time");

        let total_hashes = hashes.len();
        let chunks = Self::div_ceil(total_hashes, fanout);

        let result: Vec<_> = (0..chunks)
            .into_par_iter()
            .map(|i| {
                let start_index = i * fanout;
                let end_index = std::cmp::min(start_index + fanout, total_hashes);

                let mut hasher = Hasher::default();
                for item in hashes.iter().take(end_index).skip(start_index) {
                    let h = extractor(item);
                    hasher.hash(h.as_ref());
                }

                hasher.result()
            })
            .collect();
        time.stop();
        debug!("hashing {} {}", total_hashes, time);

        if result.len() == 1 {
            result[0]
        } else {
            Self::compute_merkle_root_recurse(result, fanout)
        }
    }
// For the first iteration, there could be more items in the tuple than just hash and lamports.
// Using extractor allows us to avoid an unnecessary array copy on the first iteration.
For the first iteration, there could be more items in the tuple than just hash and lamports.
Using extractor allows us to avoid an unnecessary array copy on the first iteration.
For the first iteration there could be more items in the tuple than just hash and lamports . Using extractor allows us to avoid an unnecessary array copy on the first iteration .
pub fn compute_merkle_root_loop<T, F>(hashes: Vec<T>, fanout: usize, extractor: F) -> Hash
    where
        F: Fn(&T) -> Hash + std::marker::Sync,
        T: std::marker::Sync,
    {
        if hashes.is_empty() {
            return Hasher::default().result();
        }
        let mut time = Measure::start("time");
        let total_hashes = hashes.len();
        let chunks = Self::div_ceil(total_hashes, fanout);
        let result: Vec<_> = (0..chunks)
            .into_par_iter()
            .map(|i| {
                let start_index = i * fanout;
                let end_index = std::cmp::min(start_index + fanout, total_hashes);
                let mut hasher = Hasher::default();
                for item in hashes.iter().take(end_index).skip(start_index) {
                    let h = extractor(item);
                    hasher.hash(h.as_ref());
                }
                hasher.result()
            })
            .collect();
        time.stop();
        debug!("hashing {} {}", total_hashes, time);
        if result.len() == 1 {
            result[0]
        } else {
            Self::compute_merkle_root_recurse(result, fanout)
        }
    }
pub fn compute_merkle_root_loop < T , F > ( hashes : Vec < T > , fanout : usize , extractor : F ) -> Hash where F : Fn ( & T ) -> Hash + std :: marker :: Sync , T : std :: marker :: Sync , { if hashes . is_empty ( ) { return Hasher :: default ( ) . result ( ) ; } let mut time = Measure :: start ( " " ) ; let total_hashes = hashes . len ( ) ; let chunks = Self :: div_ceil ( total_hashes , fanout ) ; let result : Vec < _ > = ( 0 .. chunks ) . into_par_iter ( ) . map ( | i | { let start_index = i * fanout ; let end_index = std :: cmp :: min ( start_index + fanout , total_hashes ) ; let mut hasher = Hasher :: default ( ) ; for item in hashes . iter ( ) . take ( end_index ) . skip ( start_index ) { let h = extractor ( item ) ; hasher . hash ( h . as_ref ( ) ) ; } hasher . result ( ) } ) . collect ( ) ; time . stop ( ) ; debug ! ( " " total_hashes time ) ; if result . len ( ) == 1 { result [ 0 ] } else { Self :: compute_merkle_root_recurse ( result , fanout ) } }
For the first iteration, there could be more items in the tuple than just hash and lamports.
For the first iteration there could be more items in the tuple than just hash and lamports .
hashes
Vec<T>
fanout
usize
extractor
F