Skip to content

Commit 41ad2be

Browse files
committed
mempool: Avoid expensive loop in removeForBlock during IBD
During Initial Block Download, the mempool is usually empty, but `CTxMemPool::removeForBlock` is still called for every connected block where we: * iterate over every transaction in the block even though none will be found in the empty `mapTx`, always leaving `txs_removed_for_block` empty... * which is pre-allocated regardless with 40 bytes * vtx.size(), even though it will always remain empty. This change introduces a minor performance optimization by only executing the loop if any of the core mempool maps have any contents. The call to `MempoolTransactionsRemovedForBlock` and the updates to the rolling fee logic remain unchanged. The `removeForBlock` was also updated stylistically to match the surrounding methods and a clarification was added to clarify that it affects fee estimation as well.
1 parent e9edd43 commit 41ad2be

File tree

1 file changed

+13
-14
lines changed

1 file changed

+13
-14
lines changed

src/txmempool.cpp

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -661,26 +661,25 @@ void CTxMemPool::removeConflicts(const CTransaction &tx)
661661
}
662662
}
663663

664-
/**
665-
* Called when a block is connected. Removes from mempool.
666-
*/
667664
void CTxMemPool::removeForBlock(const std::vector<CTransactionRef>& vtx, unsigned int nBlockHeight)
668665
{
666+
// Remove confirmed txs and conflicts when a new block is connected, updating the fee logic
669667
AssertLockHeld(cs);
670668
Assume(!m_have_changeset);
671669
std::vector<RemovedMempoolTransactionInfo> txs_removed_for_block;
672-
txs_removed_for_block.reserve(vtx.size());
673-
for (const auto& tx : vtx)
674-
{
675-
txiter it = mapTx.find(tx->GetHash());
676-
if (it != mapTx.end()) {
677-
setEntries stage;
678-
stage.insert(it);
679-
txs_removed_for_block.emplace_back(*it);
680-
RemoveStaged(stage, true, MemPoolRemovalReason::BLOCK);
670+
if (mapTx.size() || mapNextTx.size() || mapDeltas.size()) {
671+
txs_removed_for_block.reserve(vtx.size());
672+
for (const auto& tx : vtx) {
673+
txiter it = mapTx.find(tx->GetHash());
674+
if (it != mapTx.end()) {
675+
setEntries stage;
676+
stage.insert(it);
677+
txs_removed_for_block.emplace_back(*it);
678+
RemoveStaged(stage, true, MemPoolRemovalReason::BLOCK);
679+
}
680+
removeConflicts(*tx);
681+
ClearPrioritisation(tx->GetHash());
681682
}
682-
removeConflicts(*tx);
683-
ClearPrioritisation(tx->GetHash());
684683
}
685684
if (m_opts.signals) {
686685
m_opts.signals->MempoolTransactionsRemovedForBlock(txs_removed_for_block, nBlockHeight);

0 commit comments

Comments
 (0)