From eed816af6c68c0c67f5fc05472a3927db62f8a18 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Mon, 6 Mar 2017 11:16:06 -0500 Subject: [PATCH 1/3] Mining: return early when block is almost full --- src/miner.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/miner.cpp b/src/miner.cpp index 67e7ff155..570053a53 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -358,6 +358,13 @@ void BlockAssembler::addPackageTxs() CTxMemPool::indexed_transaction_set::index::type::iterator mi = mempool.mapTx.get().begin(); CTxMemPool::txiter iter; + + // Limit the number of attempts to add transactions to the block when it is + // close to full; this is just a simple heuristic to finish quickly if the + // mempool has a lot of entries. + const int64_t MAX_CONSECUTIVE_FAILURES = 1000; + int64_t nConsecutiveFailed = 0; + while (mi != mempool.mapTx.get().end() || !mapModifiedTx.empty()) { // First try to find a new transaction in mapTx to evaluate. @@ -419,6 +426,14 @@ void BlockAssembler::addPackageTxs() mapModifiedTx.get().erase(modit); failedTx.insert(iter); } + + ++nConsecutiveFailed; + + if (nConsecutiveFailed > MAX_CONSECUTIVE_FAILURES && nBlockWeight > + nBlockMaxWeight - 4000) { + // Give up if we're close to full and haven't succeeded in a while + break; + } continue; } @@ -439,6 +454,9 @@ void BlockAssembler::addPackageTxs() continue; } + // This transaction will make it in; reset the failed counter. + nConsecutiveFailed = 0; + // Package can be added. Sort the entries in a valid order. std::vector sortedEntries; SortForBlock(ancestors, iter, sortedEntries); From 42cd8c890fb2d65274f26edf95b6d52ac41fcab8 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Wed, 8 Mar 2017 10:17:58 -0500 Subject: [PATCH 2/3] Add benchmarking for CreateNewBlock --- src/miner.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/miner.cpp b/src/miner.cpp index 570053a53..ffde2ed80 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -139,6 +139,8 @@ void BlockAssembler::resetBlock() std::unique_ptr BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn) { + int64_t nTimeStart = GetTimeMicros(); + resetBlock(); pblocktemplate.reset(new CBlockTemplate()); @@ -179,6 +181,8 @@ std::unique_ptr BlockAssembler::CreateNewBlock(const CScript& sc addPackageTxs(); + int64_t nTime1 = GetTimeMicros(); + nLastBlockTx = nBlockTx; nLastBlockSize = nBlockSize; nLastBlockWeight = nBlockWeight; @@ -209,6 +213,9 @@ std::unique_ptr BlockAssembler::CreateNewBlock(const CScript& sc if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) { throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, FormatStateMessage(state))); } + int64_t nTime2 = GetTimeMicros(); + + LogPrint("bench", "CreateNewBlock() packages: %.2fms, validity: %.2fms (total %.2fms)\n", 0.001 * (nTime1 - nTimeStart), 0.001 * (nTime2 - nTime1), 0.001 * (nTime2 - nTimeStart)); return std::move(pblocktemplate); } From 011124a2b278c5a60bad5f1b0b4abbf7ebc95aa0 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Wed, 8 Mar 2017 10:56:29 -0500 Subject: [PATCH 3/3] Update benchmarking with package statistics --- src/miner.cpp | 17 ++++++++++++----- src/miner.h | 11 +++++++---- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/miner.cpp b/src/miner.cpp index ffde2ed80..224998438 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -179,7 +179,9 @@ std::unique_ptr BlockAssembler::CreateNewBlock(const CScript& sc // transaction (which in most cases can be a no-op). fIncludeWitness = IsWitnessEnabled(pindexPrev, chainparams.GetConsensus()); - addPackageTxs(); + int nPackagesSelected = 0; + int nDescendantsUpdated = 0; + addPackageTxs(nPackagesSelected, nDescendantsUpdated); int64_t nTime1 = GetTimeMicros(); @@ -215,7 +217,7 @@ std::unique_ptr BlockAssembler::CreateNewBlock(const CScript& sc } int64_t nTime2 = GetTimeMicros(); - LogPrint("bench", "CreateNewBlock() packages: %.2fms, validity: %.2fms (total %.2fms)\n", 0.001 * (nTime1 - nTimeStart), 0.001 * (nTime2 - nTime1), 0.001 * (nTime2 - nTimeStart)); + 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)); return std::move(pblocktemplate); } @@ -289,9 +291,10 @@ void BlockAssembler::AddToBlock(CTxMemPool::txiter iter) } } -void BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& alreadyAdded, +int BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& alreadyAdded, indexed_modified_transaction_set &mapModifiedTx) { + int nDescendantsUpdated = 0; BOOST_FOREACH(const CTxMemPool::txiter it, alreadyAdded) { CTxMemPool::setEntries descendants; mempool.CalculateDescendants(it, descendants); @@ -299,6 +302,7 @@ void BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& alread BOOST_FOREACH(CTxMemPool::txiter desc, descendants) { if (alreadyAdded.count(desc)) continue; + ++nDescendantsUpdated; modtxiter mit = mapModifiedTx.find(desc); if (mit == mapModifiedTx.end()) { CTxMemPoolModifiedEntry modEntry(desc); @@ -311,6 +315,7 @@ void BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& alread } } } + return nDescendantsUpdated; } // Skip entries in mapTx that are already in a block or are present @@ -351,7 +356,7 @@ void BlockAssembler::SortForBlock(const CTxMemPool::setEntries& package, CTxMemP // Each time through the loop, we compare the best transaction in // mapModifiedTxs with the next transaction in the mempool to decide what // transaction package to work on next. -void BlockAssembler::addPackageTxs() +void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpdated) { // mapModifiedTx will store sorted packages after they are modified // because some of their txs are already in the block @@ -474,8 +479,10 @@ void BlockAssembler::addPackageTxs() mapModifiedTx.erase(sortedEntries[i]); } + ++nPackagesSelected; + // Update transactions that depend on each of these - UpdatePackagesForAdded(ancestors, mapModifiedTx); + nDescendantsUpdated += UpdatePackagesForAdded(ancestors, mapModifiedTx); } } diff --git a/src/miner.h b/src/miner.h index c105d07c2..cd225cabc 100644 --- a/src/miner.h +++ b/src/miner.h @@ -180,8 +180,10 @@ private: void AddToBlock(CTxMemPool::txiter iter); // Methods for how to add transactions to a block. - /** Add transactions based on feerate including unconfirmed ancestors */ - void addPackageTxs(); + /** Add transactions based on feerate including unconfirmed ancestors + * Increments nPackagesSelected / nDescendantsUpdated with corresponding + * statistics from the package selection (for logging statistics). */ + void addPackageTxs(int &nPackagesSelected, int &nDescendantsUpdated); // helper functions for addPackageTxs() /** Remove confirmed (inBlock) entries from given set */ @@ -199,8 +201,9 @@ private: /** Sort the package in an order that is valid to appear in a block */ void SortForBlock(const CTxMemPool::setEntries& package, CTxMemPool::txiter entry, std::vector& sortedEntries); /** Add descendants of given transactions to mapModifiedTx with ancestor - * state updated assuming given transactions are inBlock. */ - void UpdatePackagesForAdded(const CTxMemPool::setEntries& alreadyAdded, indexed_modified_transaction_set &mapModifiedTx); + * state updated assuming given transactions are inBlock. Returns number + * of updated descendants. */ + int UpdatePackagesForAdded(const CTxMemPool::setEntries& alreadyAdded, indexed_modified_transaction_set &mapModifiedTx); }; /** Modify the extranonce in a block */