Skip to content

Commit 24064da

Browse files
Merge #6835: perf(qt): reduce consequent calls of updateVotingCapability for each block
dacbacc perf: avoid calling updateVotingCapability for each block update (Konstantin Akimov) 1525731 refactor: use unique_ptr instead of shared_ptr in clientmodel for CDeterministicMNList (Konstantin Akimov) Pull request description: ## Issue being fixed or feature implemented Currently, there are 2 handlers for governance in Qt app: `updateProposalList` and `updateVotingCapability`. `updateVotingCapability` is calling for each block; `updateProposalList` is calling once in 10 seconds. Calling `updateVotingCapability` for each block is very inefficient because during reindex this handler takes uses one full CPU core on my laptop and make Qt app very irresponsible and lagging; it could take up to 10-60 seconds to see an input text in RPC console or react to click. ## What was done? Call `updateVotingCapability` for each call of `updateProposalList`, no more often. Minor improvement: use unique_ptr instead shared_ptr in ClientModel: it returns a copy of object anyway currently instead shared_ptr. ## How Has This Been Tested? This PR makes `updateVotingCapability` disappear from the top of profiler. ## Breaking Changes N/A ## Checklist: - [x] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone ACKs for top commit: UdjinM6: utACK dacbacc kwvg: utACK dacbacc Tree-SHA512: b97e0bb700104e2dd6d9bc5407c7e36592b9b7c0e0ec2a329482fc8509da8f38e57f8c95f05d560541cc837531740df55c59c5b3fb2311a21eedeaeeb6854262
2 parents f2bc508 + dacbacc commit 24064da

File tree

3 files changed

+17
-18
lines changed

3 files changed

+17
-18
lines changed

src/qt/clientmodel.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ ClientModel::ClientModel(interfaces::Node& node, OptionsModel *_optionsModel, QO
5050
m_peer_table_sort_proxy->setSourceModel(peerTableModel);
5151

5252
banTableModel = new BanTableModel(m_node, this);
53-
mnListCached = std::make_shared<CDeterministicMNList>();
53+
mnListCached = std::make_unique<CDeterministicMNList>();
5454

5555
QTimer* timer = new QTimer;
5656
timer->setInterval(MODEL_UPDATE_DELAY);
@@ -101,26 +101,26 @@ int ClientModel::getNumConnections(unsigned int flags) const
101101

102102
void ClientModel::setMasternodeList(const CDeterministicMNList& mnList, const CBlockIndex* tip)
103103
{
104-
LOCK(cs_mnlinst);
104+
LOCK(cs_mnlist);
105105
if (mnListCached->GetBlockHash() == mnList.GetBlockHash()) {
106106
return;
107107
}
108-
mnListCached = std::make_shared<CDeterministicMNList>(mnList);
108+
mnListCached = std::make_unique<CDeterministicMNList>(mnList);
109109
mnListTip = tip;
110110
Q_EMIT masternodeListChanged();
111111
}
112112

113113
std::pair<CDeterministicMNList, const CBlockIndex*> ClientModel::getMasternodeList() const
114114
{
115-
LOCK(cs_mnlinst);
115+
LOCK(cs_mnlist);
116116
return {*mnListCached, mnListTip};
117117
}
118118

119119
void ClientModel::refreshMasternodeList()
120120
{
121121
auto [mnList, tip] = m_node.evo().getListAtChainTip();
122122

123-
LOCK(cs_mnlinst);
123+
LOCK(cs_mnlist);
124124
setMasternodeList(mnList, tip);
125125
}
126126

src/qt/clientmodel.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ enum NumConnections {
4646

4747
class CDeterministicMNList;
4848
class CGovernanceObject;
49-
typedef std::shared_ptr<CDeterministicMNList> CDeterministicMNListPtr;
5049

5150
/** Model for Dash network client. */
5251
class ClientModel : public QObject
@@ -116,8 +115,8 @@ class ClientModel : public QObject
116115
// The cache for mn list is not technically needed because CDeterministicMNManager
117116
// caches it internally for recent blocks but it's not enough to get consistent
118117
// representation of the list in UI during initial sync/reindex, so we cache it here too.
119-
mutable RecursiveMutex cs_mnlinst; // protects mnListCached
120-
CDeterministicMNListPtr mnListCached;
118+
mutable RecursiveMutex cs_mnlist; // protects mnListCached
119+
std::unique_ptr<CDeterministicMNList> mnListCached GUARDED_BY(cs_mnlist){};
121120
const CBlockIndex* mnListTip{nullptr};
122121

123122
void TipChanged(SynchronizationState sync_state, interfaces::BlockTip tip, double verification_progress, bool header);

src/qt/governancelist.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <qt/governancelist.h>
88
#include <qt/proposalwizard.h>
99

10+
#include <chain.h>
1011
#include <chainparams.h>
1112
#include <chainparamsbase.h>
1213
#include <evo/deterministicmns.h>
@@ -360,16 +361,10 @@ GovernanceList::~GovernanceList() = default;
360361
void GovernanceList::setClientModel(ClientModel* model)
361362
{
362363
this->clientModel = model;
363-
updateProposalList();
364364
if (model != nullptr) {
365365
connect(model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &GovernanceList::updateDisplayUnit);
366366

367-
// Update voting capability if we now have both client and wallet models
368-
if (walletModel) {
369-
updateVotingCapability();
370-
// Update voting capability when masternode list changes
371-
connect(clientModel, &ClientModel::masternodeListChanged, this, &GovernanceList::updateVotingCapability);
372-
}
367+
updateProposalList();
373368
}
374369
}
375370

@@ -410,6 +405,11 @@ void GovernanceList::updateProposalList()
410405
newProposals.emplace_back(new Proposal(this->clientModel, govObj, proposalModel));
411406
}
412407
proposalModel->reconcile(newProposals);
408+
// Update voting capability if we now have both client and wallet models
409+
410+
if (walletModel) {
411+
updateVotingCapability();
412+
}
413413
}
414414

415415
// Schedule next update.
@@ -489,11 +489,11 @@ void GovernanceList::updateVotingCapability()
489489
{
490490
if (!walletModel || !clientModel) return;
491491

492-
votableMasternodes.clear();
493-
auto [mnList, pindex] = clientModel->getMasternodeList();
492+
auto [mn_list, pindex] = clientModel->getMasternodeList();
494493
if (!pindex) return;
495494

496-
mnList.ForEachMN(true, [&](const auto& dmn) {
495+
votableMasternodes.clear();
496+
mn_list.ForEachMN(true, [&](const auto& dmn) {
497497
// Check if wallet owns the voting key using the same logic as RPC
498498
const CScript script = GetScriptForDestination(PKHash(dmn.pdmnState->keyIDVoting));
499499
if (walletModel->wallet().isSpendable(script)) {

0 commit comments

Comments
 (0)