aboutsummaryrefslogtreecommitdiff
path: root/src/validation.cpp
diff options
context:
space:
mode:
authorMatt Corallo <git@bluematt.me>2016-10-15 12:12:50 -0400
committerMatt Corallo <git@bluematt.me>2016-12-04 00:13:09 -0800
commitfd9d89070a70a7333d8ffe944cc53f8fd4122548 (patch)
tree4ae20662e1460c891112abd0af3181b3696cdca9 /src/validation.cpp
parent6fdd43b968f984ef92ca4576872dc65462ba7312 (diff)
Keep blocks as shared_ptrs, instead of copying txn in ConnectTip
Diffstat (limited to 'src/validation.cpp')
-rw-r--r--src/validation.cpp25
1 files changed, 16 insertions, 9 deletions
diff --git a/src/validation.cpp b/src/validation.cpp
index e8fe8639fb..ffb4732666 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -2158,7 +2158,7 @@ static int64_t nTimePostConnect = 0;
*/
struct ConnectTrace {
std::vector<CTransactionRef> txConflicted;
- std::vector<std::tuple<CTransactionRef,CBlockIndex*,int>> txChanged;
+ std::vector<std::pair<CBlockIndex*, std::shared_ptr<const CBlock> > > blocksConnected;
};
/**
@@ -2170,11 +2170,15 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams,
assert(pindexNew->pprev == chainActive.Tip());
// Read block from disk.
int64_t nTime1 = GetTimeMicros();
- CBlock block;
if (!pblock) {
- if (!ReadBlockFromDisk(block, pindexNew, chainparams.GetConsensus()))
+ std::shared_ptr<CBlock> pblockNew = std::make_shared<CBlock>();
+ connectTrace.blocksConnected.emplace_back(pindexNew, pblockNew);
+ if (!ReadBlockFromDisk(*pblockNew, pindexNew, chainparams.GetConsensus()))
return AbortNode(state, "Failed to read block");
- pblock = &block;
+ pblock = pblockNew.get();
+ } else {
+ //TODO: This copy is a major performance regression, but ProcessNewBlock callers need updated to fix this
+ connectTrace.blocksConnected.emplace_back(pindexNew, std::make_shared<const CBlock>(*pblock));
}
// Apply the block atomically to the chain state.
int64_t nTime2 = GetTimeMicros(); nTimeReadFromDisk += nTime2 - nTime1;
@@ -2205,9 +2209,6 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams,
// Update chainActive & related variables.
UpdateTip(pindexNew, chainparams);
- for (unsigned int i=0; i < pblock->vtx.size(); i++)
- connectTrace.txChanged.emplace_back(pblock->vtx[i], pindexNew, i);
-
int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1;
LogPrint("bench", " - Connect postprocess: %.2fms [%.2fs]\n", (nTime6 - nTime5) * 0.001, nTimePostConnect * 0.000001);
LogPrint("bench", "- Connect block: %.2fms [%.2fs]\n", (nTime6 - nTime1) * 0.001, nTimeTotal * 0.000001);
@@ -2329,6 +2330,8 @@ static bool ActivateBestChainStep(CValidationState& state, const CChainParams& c
state = CValidationState();
fInvalidFound = true;
fContinue = false;
+ // If we didn't actually connect the block, don't notify listeners about it
+ connectTrace.blocksConnected.pop_back();
break;
} else {
// A system error occurred (disk space, database error, ...).
@@ -2431,8 +2434,12 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
GetMainSignals().SyncTransaction(*tx, pindexNewTip, CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK);
}
// ... and about transactions that got confirmed:
- for (unsigned int i = 0; i < connectTrace.txChanged.size(); i++)
- GetMainSignals().SyncTransaction(*std::get<0>(connectTrace.txChanged[i]), std::get<1>(connectTrace.txChanged[i]), std::get<2>(connectTrace.txChanged[i]));
+ for (const auto& pair : connectTrace.blocksConnected) {
+ assert(pair.second);
+ const CBlock& block = *(pair.second);
+ for (unsigned int i = 0; i < block.vtx.size(); i++)
+ GetMainSignals().SyncTransaction(*block.vtx[i], pair.first, i);
+ }
// Notify external listeners about the new tip.
GetMainSignals().UpdatedBlockTip(pindexNewTip, pindexFork, fInitialDownload);