mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-08-24 18:01:32 +02:00
Merge bitcoin/bitcoin#32827: mempool: Avoid needless vtx iteration during IBD
249889bee6
orphanage: avoid vtx iteration when no orphans (furszy)41ad2be434
mempool: Avoid expensive loop in `removeForBlock` during IBD (Lőrinc) Pull request description: 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. Similarly to https://github.com/bitcoin/bitcoin/pull/32730#discussion_r2140691354, this change introduces a minor performance & memory optimization by only executing the loop if any of the affected mempool maps have any contents. The second commit is cherry-picked from there since it's related to this change as well. ACKs for top commit: optout21: ACK249889bee6
glozow: ACK249889bee6
ismaelsadeeq: reACK249889bee6
Tree-SHA512: 80d06ff1515164529cdc3ad21db3041bb5b2a1d4b72ba9e6884cdf40c5f1477fee7479944b8bca32a6f0bf27c4e5501fccd085f6041a2dbb101438629cfb9e4b
This commit is contained in:
@@ -567,6 +567,8 @@ bool TxOrphanageImpl::HaveTxToReconsider(NodeId peer)
|
|||||||
}
|
}
|
||||||
void TxOrphanageImpl::EraseForBlock(const CBlock& block)
|
void TxOrphanageImpl::EraseForBlock(const CBlock& block)
|
||||||
{
|
{
|
||||||
|
if (m_orphans.empty()) return;
|
||||||
|
|
||||||
std::set<Wtxid> wtxids_to_erase;
|
std::set<Wtxid> wtxids_to_erase;
|
||||||
for (const CTransactionRef& ptx : block.vtx) {
|
for (const CTransactionRef& ptx : block.vtx) {
|
||||||
const CTransaction& block_tx = *ptx;
|
const CTransaction& block_tx = *ptx;
|
||||||
|
@@ -661,26 +661,25 @@ void CTxMemPool::removeConflicts(const CTransaction &tx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a block is connected. Removes from mempool.
|
|
||||||
*/
|
|
||||||
void CTxMemPool::removeForBlock(const std::vector<CTransactionRef>& vtx, unsigned int nBlockHeight)
|
void CTxMemPool::removeForBlock(const std::vector<CTransactionRef>& vtx, unsigned int nBlockHeight)
|
||||||
{
|
{
|
||||||
|
// Remove confirmed txs and conflicts when a new block is connected, updating the fee logic
|
||||||
AssertLockHeld(cs);
|
AssertLockHeld(cs);
|
||||||
Assume(!m_have_changeset);
|
Assume(!m_have_changeset);
|
||||||
std::vector<RemovedMempoolTransactionInfo> txs_removed_for_block;
|
std::vector<RemovedMempoolTransactionInfo> txs_removed_for_block;
|
||||||
txs_removed_for_block.reserve(vtx.size());
|
if (mapTx.size() || mapNextTx.size() || mapDeltas.size()) {
|
||||||
for (const auto& tx : vtx)
|
txs_removed_for_block.reserve(vtx.size());
|
||||||
{
|
for (const auto& tx : vtx) {
|
||||||
txiter it = mapTx.find(tx->GetHash());
|
txiter it = mapTx.find(tx->GetHash());
|
||||||
if (it != mapTx.end()) {
|
if (it != mapTx.end()) {
|
||||||
setEntries stage;
|
setEntries stage;
|
||||||
stage.insert(it);
|
stage.insert(it);
|
||||||
txs_removed_for_block.emplace_back(*it);
|
txs_removed_for_block.emplace_back(*it);
|
||||||
RemoveStaged(stage, true, MemPoolRemovalReason::BLOCK);
|
RemoveStaged(stage, true, MemPoolRemovalReason::BLOCK);
|
||||||
|
}
|
||||||
|
removeConflicts(*tx);
|
||||||
|
ClearPrioritisation(tx->GetHash());
|
||||||
}
|
}
|
||||||
removeConflicts(*tx);
|
|
||||||
ClearPrioritisation(tx->GetHash());
|
|
||||||
}
|
}
|
||||||
if (m_opts.signals) {
|
if (m_opts.signals) {
|
||||||
m_opts.signals->MempoolTransactionsRemovedForBlock(txs_removed_for_block, nBlockHeight);
|
m_opts.signals->MempoolTransactionsRemovedForBlock(txs_removed_for_block, nBlockHeight);
|
||||||
|
Reference in New Issue
Block a user