From f2a3c27e881df2f5f2ff1a50493fe7720377374d Mon Sep 17 00:00:00 2001 From: greg7mdp Date: Sat, 30 Mar 2024 16:51:59 -0400 Subject: [PATCH] Update `calculate_merkle_pow2` to use 2 threads for sizes from 256 to 2048. --- libraries/chain/controller.cpp | 2 +- .../chain/include/eosio/chain/merkle.hpp | 29 ++++++++++++------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index 58757b5fa7..3986ebedce 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -707,7 +707,7 @@ struct building_block { // compute the action_mroot and transaction_mroot auto [transaction_mroot, action_mroot] = std::visit( overloaded{[&](digests_t& trx_receipts) { - return std::make_pair(calculate_merkle(trx_receipts), // ~15us for 100 digests + return std::make_pair(calculate_merkle(trx_receipts), // ~0.06ms for 300 digests calculate_merkle(*action_receipts.digests_s)); }, [&](const checksum256_type& trx_checksum) { diff --git a/libraries/chain/include/eosio/chain/merkle.hpp b/libraries/chain/include/eosio/chain/merkle.hpp index 91d26d5e21..2538d516f4 100644 --- a/libraries/chain/include/eosio/chain/merkle.hpp +++ b/libraries/chain/include/eosio/chain/merkle.hpp @@ -31,19 +31,28 @@ inline digest_type calculate_merkle_pow2(const It& start, const It& end) { if (size == 2) return hash_combine(start[0], start[1]); else { - if (async && size >= 4096) { // below 4096, starting async threads is overkill - std::array, 4> fut; // size dictates the number of threads (must be power of two) - size_t slice_size = size / fut.size(); + if (async && size >= 256) { + auto async_calculate_merkle_pow2 = [&start, &size](auto fut) { + size_t slice_size = size / fut.size(); - for (size_t i=0; i, - start + slice_size * i, start + slice_size * (i+1)); + for (size_t i=0; i, + start + slice_size * i, start + slice_size * (i+1)); - std::array res; - for (size_t i=0; i res; - return calculate_merkle_pow2(res.begin(), res.end()); + for (size_t i=0; i= 2048) { + // use 4 threads. Future array size dictates the number of threads (must be power of two) + return async_calculate_merkle_pow2(std::array, 4>()); + } + // use 2 threads. Future array size dictates the number of threads (must be power of two) + return async_calculate_merkle_pow2(std::array, 2>()); } else { auto mid = start + size / 2; return hash_combine(calculate_merkle_pow2(start, mid), calculate_merkle_pow2(mid, end));