aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Corallo <git@bluematt.me>2016-12-04 00:17:30 -0800
committerMatt Corallo <git@bluematt.me>2016-12-04 00:17:30 -0800
commit2d6e5619afa2d43a37a0a38daf33f58965ddfa80 (patch)
tree9bdc85dfd1048bc7d7f2d535d9f63b3b373ef4d9
parent2736c44c8edea5ce6a502a04269926fecda27301 (diff)
downloadbitcoin-2d6e5619afa2d43a37a0a38daf33f58965ddfa80.tar.xz
Switch pblock in ProcessNewBlock to a shared_ptr
This (finally) fixes a performance regression in b3b3c2a5623d5c942d2b3565cc2d833c65105555
-rw-r--r--src/net_processing.cpp16
-rw-r--r--src/rpc/mining.cpp8
-rw-r--r--src/test/miner_tests.cpp3
-rw-r--r--src/test/test_bitcoin.cpp3
-rw-r--r--src/validation.cpp9
-rw-r--r--src/validation.h2
6 files changed, 20 insertions, 21 deletions
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index 747167264b..e81332d618 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -1895,7 +1895,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
BlockTransactions resp;
vRecv >> resp;
- CBlock block;
+ std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
bool fBlockRead = false;
{
LOCK(cs_main);
@@ -1908,7 +1908,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
PartiallyDownloadedBlock& partialBlock = *it->second.second->partialBlock;
- ReadStatus status = partialBlock.FillBlock(block, resp.txn);
+ ReadStatus status = partialBlock.FillBlock(*pblock, resp.txn);
if (status == READ_STATUS_INVALID) {
MarkBlockAsReceived(resp.blockhash); // Reset in-flight state in case of whitelist
Misbehaving(pfrom->GetId(), 100);
@@ -1951,7 +1951,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
bool fNewBlock = false;
// Since we requested this block (it was in mapBlocksInFlight), force it to be processed,
// even if it would not be a candidate for new tip (missing previous block, chain not long enough, etc)
- ProcessNewBlock(chainparams, &block, true, NULL, &fNewBlock);
+ ProcessNewBlock(chainparams, pblock, true, NULL, &fNewBlock);
if (fNewBlock)
pfrom->nLastBlockTime = GetTime();
}
@@ -2112,17 +2112,17 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
else if (strCommand == NetMsgType::BLOCK && !fImporting && !fReindex) // Ignore blocks received while importing
{
- CBlock block;
- vRecv >> block;
+ std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
+ vRecv >> *pblock;
- LogPrint("net", "received block %s peer=%d\n", block.GetHash().ToString(), pfrom->id);
+ LogPrint("net", "received block %s peer=%d\n", pblock->GetHash().ToString(), pfrom->id);
// Process all blocks from whitelisted peers, even if not requested,
// unless we're still syncing with the network.
// Such an unrequested block may still be processed, subject to the
// conditions in AcceptBlock().
bool forceProcessing = pfrom->fWhitelisted && !IsInitialBlockDownload();
- const uint256 hash(block.GetHash());
+ const uint256 hash(pblock->GetHash());
{
LOCK(cs_main);
// Also always process if we requested the block explicitly, as we may
@@ -2133,7 +2133,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
mapBlockSource.emplace(hash, std::make_pair(pfrom->GetId(), true));
}
bool fNewBlock = false;
- ProcessNewBlock(chainparams, &block, forceProcessing, NULL, &fNewBlock);
+ ProcessNewBlock(chainparams, pblock, forceProcessing, NULL, &fNewBlock);
if (fNewBlock)
pfrom->nLastBlockTime = GetTime();
}
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 61408b3b60..cb22dec342 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -131,7 +131,8 @@ UniValue generateBlocks(boost::shared_ptr<CReserveScript> coinbaseScript, int nG
if (pblock->nNonce == nInnerLoopCount) {
continue;
}
- if (!ProcessNewBlock(Params(), pblock, true, NULL, NULL))
+ std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(*pblock);
+ if (!ProcessNewBlock(Params(), shared_pblock, true, NULL, NULL))
throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
++nHeight;
blockHashes.push_back(pblock->GetHash().GetHex());
@@ -728,7 +729,8 @@ UniValue submitblock(const JSONRPCRequest& request)
+ HelpExampleRpc("submitblock", "\"mydata\"")
);
- CBlock block;
+ std::shared_ptr<CBlock> blockptr = std::make_shared<CBlock>();
+ CBlock& block = *blockptr;
if (!DecodeHexBlk(block, request.params[0].get_str()))
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
@@ -758,7 +760,7 @@ UniValue submitblock(const JSONRPCRequest& request)
submitblock_StateCatcher sc(block.GetHash());
RegisterValidationInterface(&sc);
- bool fAccepted = ProcessNewBlock(Params(), &block, true, NULL, NULL);
+ bool fAccepted = ProcessNewBlock(Params(), blockptr, true, NULL, NULL);
UnregisterValidationInterface(&sc);
if (fBlockPresent)
{
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index ca703841db..bc1bdd8874 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -223,7 +223,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
txFirst.push_back(pblock->vtx[0]);
pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
pblock->nNonce = blockinfo[i].nonce;
- BOOST_CHECK(ProcessNewBlock(chainparams, pblock, true, NULL, NULL));
+ std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(*pblock);
+ BOOST_CHECK(ProcessNewBlock(chainparams, shared_pblock, true, NULL, NULL));
pblock->hashPrevBlock = pblock->GetHash();
}
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index f979d01a37..139389117a 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -127,7 +127,8 @@ TestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransaction>&
while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce;
- ProcessNewBlock(chainparams, &block, true, NULL, NULL);
+ std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(block);
+ ProcessNewBlock(chainparams, shared_pblock, true, NULL, NULL);
CBlock result = block;
return result;
diff --git a/src/validation.cpp b/src/validation.cpp
index bd66c5679b..0983c1f762 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -3123,7 +3123,7 @@ static bool AcceptBlock(const CBlock& block, CValidationState& state, const CCha
return true;
}
-bool ProcessNewBlock(const CChainParams& chainparams, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp, bool *fNewBlock)
+bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<const CBlock> pblock, bool fForceProcessing, const CDiskBlockPos* dbp, bool *fNewBlock)
{
{
LOCK(cs_main);
@@ -3142,13 +3142,8 @@ bool ProcessNewBlock(const CChainParams& chainparams, const CBlock* pblock, bool
NotifyHeaderTip();
- //TODO: This copy is a major performance regression, but callers need updated to fix this
- std::shared_ptr<const CBlock> block_ptr;
- if (pblock)
- block_ptr.reset(new CBlock(*pblock));
-
CValidationState state; // Only used to report errors, not invalidity - ignore it
- if (!ActivateBestChain(state, chainparams, block_ptr))
+ if (!ActivateBestChain(state, chainparams, pblock))
return error("%s: ActivateBestChain failed", __func__);
return true;
diff --git a/src/validation.h b/src/validation.h
index 2d055d1900..3a2b51bfec 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -233,7 +233,7 @@ static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024;
* @param[out] fNewBlock A boolean which is set to indicate if the block was first received via this call
* @return True if state.IsValid()
*/
-bool ProcessNewBlock(const CChainParams& chainparams, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp, bool* fNewBlock);
+bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<const CBlock> pblock, bool fForceProcessing, const CDiskBlockPos* dbp, bool* fNewBlock);
/**
* Process incoming block headers.