Skip to content

Commit

Permalink
Update calculate_merkle_pow2 to use 2 threads for sizes from 256 to…
Browse files Browse the repository at this point in the history
… 2048.
  • Loading branch information
greg7mdp committed Mar 30, 2024
1 parent b86a162 commit f2a3c27
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 11 deletions.
2 changes: 1 addition & 1 deletion libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
29 changes: 19 additions & 10 deletions libraries/chain/include/eosio/chain/merkle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::future<digest_type>, 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<fut.size(); ++i)
fut[i] = std::async(std::launch::async, calculate_merkle_pow2<It>,
start + slice_size * i, start + slice_size * (i+1));
for (size_t i=0; i<fut.size(); ++i)
fut[i] = std::async(std::launch::async, calculate_merkle_pow2<It>,
start + slice_size * i, start + slice_size * (i+1));

std::array<digest_type, fut.size()> res;
for (size_t i=0; i<fut.size(); ++i)
res[i] = fut[i].get();
std::array<digest_type, fut.size()> res;

return calculate_merkle_pow2(res.begin(), res.end());
for (size_t i=0; i<fut.size(); ++i)
res[i] = fut[i].get();

return calculate_merkle_pow2(res.begin(), res.end());
};

if (size >= 2048) {
// use 4 threads. Future array size dictates the number of threads (must be power of two)
return async_calculate_merkle_pow2(std::array<std::future<digest_type>, 4>());
}
// use 2 threads. Future array size dictates the number of threads (must be power of two)
return async_calculate_merkle_pow2(std::array<std::future<digest_type>, 2>());
} else {
auto mid = start + size / 2;
return hash_combine(calculate_merkle_pow2(start, mid), calculate_merkle_pow2(mid, end));
Expand Down

0 comments on commit f2a3c27

Please sign in to comment.