From efb4eae33861d3f316d77788f5c83b58dad94a0a Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 9 Jul 2026 12:46:30 +0000 Subject: [PATCH] clusterlin: avoid recomputing intersections in MergeChunks MergeChunks scans the top chunk's transactions twice: once to count the dependencies on the bottom chunk, and once to locate the randomly picked one. Remember the per-transaction dependency counts from the first pass, so the second pass only computes the intersection of the selected transaction, rather than one per transaction scanned. --- src/cluster_linearize.h | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/cluster_linearize.h b/src/cluster_linearize.h index aa28d04634f..7b262edb46c 100644 --- a/src/cluster_linearize.h +++ b/src/cluster_linearize.h @@ -954,11 +954,16 @@ private: Assume(m_chunk_idxs[bottom_idx]); auto& top_chunk_info = m_set_info[top_idx]; auto& bottom_chunk_info = m_set_info[bottom_idx]; - // Count the number of dependencies between bottom_chunk and top_chunk. + // Count the number of dependencies between bottom_chunk and top_chunk, remembering the + // per-transaction counts so the picking loop below does not need to recompute the + // intersections. unsigned num_deps{0}; + std::array counts; for (auto tx_idx : top_chunk_info.transactions) { auto& tx_data = m_tx_data[tx_idx]; - num_deps += (tx_data.children & bottom_chunk_info.transactions).Count(); + auto count = (tx_data.children & bottom_chunk_info.transactions).Count(); + counts[tx_idx] = count; + num_deps += count; } m_cost.MergeChunksMid(/*num_txns=*/top_chunk_info.transactions.Count()); Assume(num_deps > 0); @@ -967,10 +972,10 @@ private: unsigned num_steps = 0; for (auto tx_idx : top_chunk_info.transactions) { ++num_steps; - auto& tx_data = m_tx_data[tx_idx]; - auto intersect = tx_data.children & bottom_chunk_info.transactions; - auto count = intersect.Count(); + auto count = counts[tx_idx]; if (pick < count) { + auto& tx_data = m_tx_data[tx_idx]; + auto intersect = tx_data.children & bottom_chunk_info.transactions; for (auto child_idx : intersect) { if (pick == 0) { m_cost.MergeChunksEnd(/*num_steps=*/num_steps);