Skip to content

Commit 6dce75b

Browse files
committed
perf: cache shared_ptr to SML instead of SML list
Shared_ptr to SML is preserved between multiple CDeterministicMNList and it helps to avoid building SML from a scratch; also it helps to avoid comparision of SML item-by-item.
1 parent e9822dd commit 6dce75b

File tree

6 files changed

+25
-16
lines changed

6 files changed

+25
-16
lines changed

src/evo/cbtx.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include <consensus/validation.h>
66
#include <evo/cbtx.h>
7+
#include <evo/deterministicmns.h>
78
#include <evo/simplifiedmns.h>
89
#include <evo/specialtx.h>
910
#include <llmq/blockprocessor.h>
@@ -47,16 +48,16 @@ bool CheckCbTx(const CCbTx& cbTx, const CBlockIndex* pindexPrev, TxValidationSta
4748

4849
// This can only be done after the block has been fully processed, as otherwise we won't have the finished MN list
4950
bool CheckCbTxMerkleRoots(const CBlock& block, const CCbTx& cbTx, const CBlockIndex* pindex,
50-
const llmq::CQuorumBlockProcessor& quorum_block_processor, CSimplifiedMNList&& sml,
51-
BlockValidationState& state)
51+
const llmq::CQuorumBlockProcessor& quorum_block_processor,
52+
const CDeterministicMNList& mn_list, BlockValidationState& state)
5253
{
5354
if (pindex) {
5455
static int64_t nTimeMerkleMNL = 0;
5556
static int64_t nTimeMerkleQuorum = 0;
5657

5758
int64_t nTime1 = GetTimeMicros();
5859
uint256 calculatedMerkleRoot;
59-
if (!CalcCbTxMerkleRootMNList(calculatedMerkleRoot, std::move(sml), state)) {
60+
if (!CalcCbTxMerkleRootMNList(calculatedMerkleRoot, mn_list, state)) {
6061
// pass the state returned by the function above
6162
return false;
6263
}
@@ -88,20 +89,22 @@ bool CheckCbTxMerkleRoots(const CBlock& block, const CCbTx& cbTx, const CBlockIn
8889
return true;
8990
}
9091

91-
bool CalcCbTxMerkleRootMNList(uint256& merkleRootRet, CSimplifiedMNList&& sml, BlockValidationState& state)
92+
bool CalcCbTxMerkleRootMNList(uint256& merkleRootRet, const CDeterministicMNList& mn_list, BlockValidationState& state)
9293
{
9394
try {
9495
static std::atomic<int64_t> nTimeMerkle = 0;
9596

9697
int64_t nTime1 = GetTimeMicros();
9798

9899
static Mutex cached_mutex;
99-
static CSimplifiedMNList smlCached GUARDED_BY(cached_mutex);
100+
static std::shared_ptr<const CSimplifiedMNList> cached_sml GUARDED_BY(cached_mutex){
101+
std::make_shared<const CSimplifiedMNList>()};
100102
static uint256 merkleRootCached GUARDED_BY(cached_mutex);
101103
static bool mutatedCached GUARDED_BY(cached_mutex) {false};
102104

105+
std::shared_ptr<const CSimplifiedMNList> sml{mn_list.GetSML()};
103106
LOCK(cached_mutex);
104-
if (sml == smlCached) {
107+
if (sml == cached_sml || *sml == *cached_sml) {
105108
merkleRootRet = merkleRootCached;
106109
if (mutatedCached) {
107110
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "mutated-cached-calc-cb-mnmerkleroot");
@@ -110,14 +113,14 @@ bool CalcCbTxMerkleRootMNList(uint256& merkleRootRet, CSimplifiedMNList&& sml, B
110113
}
111114

112115
bool mutated = false;
113-
merkleRootRet = sml.CalcMerkleRoot(&mutated);
116+
merkleRootRet = sml->CalcMerkleRoot(&mutated);
114117

115118
int64_t nTime2 = GetTimeMicros();
116119
nTimeMerkle += nTime2 - nTime1;
117120
LogPrint(BCLog::BENCHMARK, " - CalcMerkleRoot: %.2fms [%.2fs]\n", 0.001 * (nTime2 - nTime1),
118121
nTimeMerkle * 0.000001);
119122

120-
smlCached = std::move(sml);
123+
cached_sml = sml;
121124
merkleRootCached = merkleRootRet;
122125
mutatedCached = mutated;
123126

src/evo/cbtx.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
class BlockValidationState;
1515
class CBlock;
1616
class CBlockIndex;
17+
class CDeterministicMNList;
1718
class TxValidationState;
18-
class CSimplifiedMNList;
1919

2020
namespace llmq {
2121
class CChainLocksHandler;
@@ -67,9 +67,9 @@ template<> struct is_serializable_enum<CCbTx::Version> : std::true_type {};
6767
bool CheckCbTx(const CCbTx& cbTx, const CBlockIndex* pindexPrev, TxValidationState& state);
6868

6969
bool CheckCbTxMerkleRoots(const CBlock& block, const CCbTx& cbTx, const CBlockIndex* pindex,
70-
const llmq::CQuorumBlockProcessor& quorum_block_processor, CSimplifiedMNList&& sml,
71-
BlockValidationState& state);
72-
bool CalcCbTxMerkleRootMNList(uint256& merkleRootRet, CSimplifiedMNList&& sml, BlockValidationState& state);
70+
const llmq::CQuorumBlockProcessor& quorum_block_processor,
71+
const CDeterministicMNList& mn_list, BlockValidationState& state);
72+
bool CalcCbTxMerkleRootMNList(uint256& merkleRootRet, const CDeterministicMNList& mn_list, BlockValidationState& state);
7373
bool CalcCbTxMerkleRootQuorums(const CBlock& block, const CBlockIndex* pindexPrev,
7474
const llmq::CQuorumBlockProcessor& quorum_block_processor, uint256& merkleRootRet,
7575
BlockValidationState& state);

src/evo/deterministicmns.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,8 @@ bool CDeterministicMNManager::ProcessBlock(const CBlock& block, gsl::not_null<co
615615
int nHeight = pindex->nHeight;
616616

617617
try {
618+
newList.GetSML(); // to fullfill cache of SML
619+
618620
LOCK(cs);
619621

620622
oldList = GetListForBlockInternal(pindex->pprev);
@@ -630,6 +632,7 @@ bool CDeterministicMNManager::ProcessBlock(const CBlock& block, gsl::not_null<co
630632

631633
diff.nHeight = pindex->nHeight;
632634
mnListDiffsCache.emplace(pindex->GetBlockHash(), diff);
635+
mnListsCache.emplace(newList.GetBlockHash(), newList);
633636
} catch (const std::exception& e) {
634637
LogPrintf("CDeterministicMNManager::%s -- internal error: %s\n", __func__, e.what());
635638
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "failed-dmn-block");
@@ -1088,7 +1091,10 @@ CDeterministicMNList CDeterministicMNManager::GetListForBlockInternal(gsl::not_n
10881091
if (tipIndex) {
10891092
// always keep a snapshot for the tip
10901093
if (snapshot.GetBlockHash() == tipIndex->GetBlockHash()) {
1091-
mnListsCache.emplace(snapshot.GetBlockHash(), snapshot);
1094+
auto hash = snapshot.GetBlockHash();
1095+
if (mnListsCache.find(hash) == mnListsCache.end()) {
1096+
mnListsCache.emplace(snapshot.GetBlockHash(), snapshot);
1097+
}
10921098
} else {
10931099
// keep snapshots for yet alive quorums
10941100
if (ranges::any_of(Params().GetConsensus().llmqs,

src/evo/specialtxman.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ bool CSpecialTxProcessor::ProcessSpecialTxsInBlock(const CBlock& block, const CB
193193
LogPrint(BCLog::BENCHMARK, " - m_dmnman: %.2fms [%.2fs]\n", 0.001 * (nTime6 - nTime5), nTimeDMN * 0.000001);
194194

195195
if (opt_cbTx.has_value()) {
196-
if (!CheckCbTxMerkleRoots(block, *opt_cbTx, pindex, m_qblockman, CSimplifiedMNList(mn_list), state)) {
196+
if (!CheckCbTxMerkleRoots(block, *opt_cbTx, pindex, m_qblockman, mn_list, state)) {
197197
// pass the state returned by the function above
198198
return false;
199199
}

src/node/miner.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
232232
if (!m_dmnman.BuildNewListFromBlock(*pblock, pindexPrev, state, m_chainstate.CoinsTip(), mn_list, m_qsnapman, true)) {
233233
throw std::runtime_error(strprintf("%s: BuildNewListFromBlock failed: %s", __func__, state.ToString()));
234234
}
235-
if (!CalcCbTxMerkleRootMNList(cbTx.merkleRootMNList, CSimplifiedMNList(mn_list), state)) {
235+
if (!CalcCbTxMerkleRootMNList(cbTx.merkleRootMNList, std::move(mn_list), state)) {
236236
throw std::runtime_error(strprintf("%s: CalcCbTxMerkleRootMNList failed: %s", __func__, state.ToString()));
237237
}
238238
if (fDIP0008Active_context) {

src/test/util/setup_common.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,7 @@ CBlock TestChainSetup::CreateBlock(
506506
if (!m_node.dmnman->BuildNewListFromBlock(block, chainstate.m_chain.Tip(), state, chainstate.CoinsTip(), mn_list, *m_node.llmq_ctx->qsnapman, true)) {
507507
Assert(false);
508508
}
509-
if (!CalcCbTxMerkleRootMNList(cbTx->merkleRootMNList, CSimplifiedMNList(mn_list), state)) {
509+
if (!CalcCbTxMerkleRootMNList(cbTx->merkleRootMNList, std::move(mn_list), state)) {
510510
Assert(false);
511511
}
512512
if (!CalcCbTxMerkleRootQuorums(block, chainstate.m_chain.Tip(), *m_node.llmq_ctx->quorum_block_processor, cbTx->merkleRootQuorums, state)) {

0 commit comments

Comments
 (0)