Skip to content

Commit cde9b1a

Browse files
committed
Merge #9959: Mining: Prevent slowdown in CreateNewBlock on large mempools
011124a Update benchmarking with package statistics (Suhas Daftuar) 42cd8c8 Add benchmarking for CreateNewBlock (Suhas Daftuar) eed816a Mining: return early when block is almost full (Suhas Daftuar) Tree-SHA512: c0d8f71e4e0441acf3f4ca12f8705e413b59b323659346a447145653def71710537fb4c6d80cad8e36d68b0aabf19c92e9eab7135a8897b053ed58720856cdda
2 parents 8ac8041 + 011124a commit cde9b1a

File tree

2 files changed

+43
-8
lines changed

2 files changed

+43
-8
lines changed

src/miner.cpp

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ void BlockAssembler::resetBlock()
126126

127127
std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn, bool fMineWitnessTx)
128128
{
129+
int64_t nTimeStart = GetTimeMicros();
130+
129131
resetBlock();
130132

131133
pblocktemplate.reset(new CBlockTemplate());
@@ -164,7 +166,11 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
164166
// transaction (which in most cases can be a no-op).
165167
fIncludeWitness = IsWitnessEnabled(pindexPrev, chainparams.GetConsensus()) && fMineWitnessTx;
166168

167-
addPackageTxs();
169+
int nPackagesSelected = 0;
170+
int nDescendantsUpdated = 0;
171+
addPackageTxs(nPackagesSelected, nDescendantsUpdated);
172+
173+
int64_t nTime1 = GetTimeMicros();
168174

169175
nLastBlockTx = nBlockTx;
170176
nLastBlockSize = nBlockSize;
@@ -196,6 +202,9 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
196202
if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) {
197203
throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, FormatStateMessage(state)));
198204
}
205+
int64_t nTime2 = GetTimeMicros();
206+
207+
LogPrint("bench", "CreateNewBlock() packages: %.2fms (%d packages, %d updated descendants), validity: %.2fms (total %.2fms)\n", 0.001 * (nTime1 - nTimeStart), nPackagesSelected, nDescendantsUpdated, 0.001 * (nTime2 - nTime1), 0.001 * (nTime2 - nTimeStart));
199208

200209
return std::move(pblocktemplate);
201210
}
@@ -269,16 +278,18 @@ void BlockAssembler::AddToBlock(CTxMemPool::txiter iter)
269278
}
270279
}
271280

272-
void BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& alreadyAdded,
281+
int BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& alreadyAdded,
273282
indexed_modified_transaction_set &mapModifiedTx)
274283
{
284+
int nDescendantsUpdated = 0;
275285
BOOST_FOREACH(const CTxMemPool::txiter it, alreadyAdded) {
276286
CTxMemPool::setEntries descendants;
277287
mempool.CalculateDescendants(it, descendants);
278288
// Insert all descendants (not yet in block) into the modified set
279289
BOOST_FOREACH(CTxMemPool::txiter desc, descendants) {
280290
if (alreadyAdded.count(desc))
281291
continue;
292+
++nDescendantsUpdated;
282293
modtxiter mit = mapModifiedTx.find(desc);
283294
if (mit == mapModifiedTx.end()) {
284295
CTxMemPoolModifiedEntry modEntry(desc);
@@ -291,6 +302,7 @@ void BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& alread
291302
}
292303
}
293304
}
305+
return nDescendantsUpdated;
294306
}
295307

296308
// Skip entries in mapTx that are already in a block or are present
@@ -331,7 +343,7 @@ void BlockAssembler::SortForBlock(const CTxMemPool::setEntries& package, CTxMemP
331343
// Each time through the loop, we compare the best transaction in
332344
// mapModifiedTxs with the next transaction in the mempool to decide what
333345
// transaction package to work on next.
334-
void BlockAssembler::addPackageTxs()
346+
void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpdated)
335347
{
336348
// mapModifiedTx will store sorted packages after they are modified
337349
// because some of their txs are already in the block
@@ -345,6 +357,13 @@ void BlockAssembler::addPackageTxs()
345357

346358
CTxMemPool::indexed_transaction_set::index<ancestor_score>::type::iterator mi = mempool.mapTx.get<ancestor_score>().begin();
347359
CTxMemPool::txiter iter;
360+
361+
// Limit the number of attempts to add transactions to the block when it is
362+
// close to full; this is just a simple heuristic to finish quickly if the
363+
// mempool has a lot of entries.
364+
const int64_t MAX_CONSECUTIVE_FAILURES = 1000;
365+
int64_t nConsecutiveFailed = 0;
366+
348367
while (mi != mempool.mapTx.get<ancestor_score>().end() || !mapModifiedTx.empty())
349368
{
350369
// First try to find a new transaction in mapTx to evaluate.
@@ -406,6 +425,14 @@ void BlockAssembler::addPackageTxs()
406425
mapModifiedTx.get<ancestor_score>().erase(modit);
407426
failedTx.insert(iter);
408427
}
428+
429+
++nConsecutiveFailed;
430+
431+
if (nConsecutiveFailed > MAX_CONSECUTIVE_FAILURES && nBlockWeight >
432+
nBlockMaxWeight - 4000) {
433+
// Give up if we're close to full and haven't succeeded in a while
434+
break;
435+
}
409436
continue;
410437
}
411438

@@ -426,6 +453,9 @@ void BlockAssembler::addPackageTxs()
426453
continue;
427454
}
428455

456+
// This transaction will make it in; reset the failed counter.
457+
nConsecutiveFailed = 0;
458+
429459
// Package can be added. Sort the entries in a valid order.
430460
std::vector<CTxMemPool::txiter> sortedEntries;
431461
SortForBlock(ancestors, iter, sortedEntries);
@@ -436,8 +466,10 @@ void BlockAssembler::addPackageTxs()
436466
mapModifiedTx.erase(sortedEntries[i]);
437467
}
438468

469+
++nPackagesSelected;
470+
439471
// Update transactions that depend on each of these
440-
UpdatePackagesForAdded(ancestors, mapModifiedTx);
472+
nDescendantsUpdated += UpdatePackagesForAdded(ancestors, mapModifiedTx);
441473
}
442474
}
443475

src/miner.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,10 @@ class BlockAssembler
180180
void AddToBlock(CTxMemPool::txiter iter);
181181

182182
// Methods for how to add transactions to a block.
183-
/** Add transactions based on feerate including unconfirmed ancestors */
184-
void addPackageTxs();
183+
/** Add transactions based on feerate including unconfirmed ancestors
184+
* Increments nPackagesSelected / nDescendantsUpdated with corresponding
185+
* statistics from the package selection (for logging statistics). */
186+
void addPackageTxs(int &nPackagesSelected, int &nDescendantsUpdated);
185187

186188
// helper functions for addPackageTxs()
187189
/** Remove confirmed (inBlock) entries from given set */
@@ -199,8 +201,9 @@ class BlockAssembler
199201
/** Sort the package in an order that is valid to appear in a block */
200202
void SortForBlock(const CTxMemPool::setEntries& package, CTxMemPool::txiter entry, std::vector<CTxMemPool::txiter>& sortedEntries);
201203
/** Add descendants of given transactions to mapModifiedTx with ancestor
202-
* state updated assuming given transactions are inBlock. */
203-
void UpdatePackagesForAdded(const CTxMemPool::setEntries& alreadyAdded, indexed_modified_transaction_set &mapModifiedTx);
204+
* state updated assuming given transactions are inBlock. Returns number
205+
* of updated descendants. */
206+
int UpdatePackagesForAdded(const CTxMemPool::setEntries& alreadyAdded, indexed_modified_transaction_set &mapModifiedTx);
204207
};
205208

206209
/** Modify the extranonce in a block */

0 commit comments

Comments
 (0)