Merge #10231: [Qt] Reduce a significant cs_main lock freeze (#1704)

4082fb0 Add missing <atomic> header in clientmodel.h (Jonas Schnelli)
928d4a9 Set both time/height header caches at the same time (Jonas Schnelli)
610a917 Declare headers height/time cache mutable, re-set the methods const (Jonas Schnelli)
cf92bce Update the remaining blocks left in modaloverlay at init. (Jonas Schnelli)
7148f5e Reduce cs_main locks during modal overlay by adding an atomic cache (Jonas Schnelli)

Tree-SHA512: a92ca22f90b8b2a5e8eb94fdce531ef44542e21a8dbbb0693f7723d7018592cb68de687a2a0aac91d31cbf019793f8e922550656d2b130ed3d854d60630341db
This commit is contained in:
Alexander Block 2017-10-31 21:14:19 +01:00 committed by UdjinM6
parent 14d11e4a8a
commit d23adcc0f1
3 changed files with 32 additions and 10 deletions

View File

@ -615,6 +615,7 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel)
connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int))); connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
connect(clientModel, SIGNAL(networkActiveChanged(bool)), this, SLOT(setNetworkActive(bool))); connect(clientModel, SIGNAL(networkActiveChanged(bool)), this, SLOT(setNetworkActive(bool)));
modalOverlay->setKnownBestHeight(clientModel->getHeaderTipHeight(), QDateTime::fromTime_t(clientModel->getHeaderTipTime()));
setNumBlocks(clientModel->getNumBlocks(), clientModel->getLastBlockDate(), clientModel->getVerificationProgress(NULL), false); setNumBlocks(clientModel->getNumBlocks(), clientModel->getLastBlockDate(), clientModel->getVerificationProgress(NULL), false);
connect(clientModel, SIGNAL(numBlocksChanged(int,QDateTime,double,bool)), this, SLOT(setNumBlocks(int,QDateTime,double,bool))); connect(clientModel, SIGNAL(numBlocksChanged(int,QDateTime,double,bool)), this, SLOT(setNumBlocks(int,QDateTime,double,bool)));
@ -644,8 +645,6 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel)
// initialize the disable state of the tray icon with the current value in the model. // initialize the disable state of the tray icon with the current value in the model.
setTrayIconVisible(optionsModel->getHideTrayIcon()); setTrayIconVisible(optionsModel->getHideTrayIcon());
} }
modalOverlay->setKnownBestHeight(clientModel->getHeaderTipHeight(), QDateTime::fromTime_t(clientModel->getHeaderTipTime()));
} else { } else {
// Disable possibility to show main window via action // Disable possibility to show main window via action
toggleHideAction->setEnabled(false); toggleHideAction->setEnabled(false);

View File

@ -42,6 +42,8 @@ ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) :
banTableModel(0), banTableModel(0),
pollTimer(0) pollTimer(0)
{ {
cachedBestHeaderHeight = -1;
cachedBestHeaderTime = -1;
peerTableModel = new PeerTableModel(this); peerTableModel = new PeerTableModel(this);
banTableModel = new BanTableModel(this); banTableModel = new BanTableModel(this);
pollTimer = new QTimer(this); pollTimer = new QTimer(this);
@ -97,18 +99,28 @@ int ClientModel::getNumBlocks() const
int ClientModel::getHeaderTipHeight() const int ClientModel::getHeaderTipHeight() const
{ {
if (cachedBestHeaderHeight == -1) {
// make sure we initially populate the cache via a cs_main lock
// otherwise we need to wait for a tip update
LOCK(cs_main); LOCK(cs_main);
if (!pindexBestHeader) if (pindexBestHeader) {
return 0; cachedBestHeaderHeight = pindexBestHeader->nHeight;
return pindexBestHeader->nHeight; cachedBestHeaderTime = pindexBestHeader->GetBlockTime();
}
}
return cachedBestHeaderHeight;
} }
int64_t ClientModel::getHeaderTipTime() const int64_t ClientModel::getHeaderTipTime() const
{ {
if (cachedBestHeaderTime == -1) {
LOCK(cs_main); LOCK(cs_main);
if (!pindexBestHeader) if (pindexBestHeader) {
return 0; cachedBestHeaderHeight = pindexBestHeader->nHeight;
return pindexBestHeader->GetBlockTime(); cachedBestHeaderTime = pindexBestHeader->GetBlockTime();
}
}
return cachedBestHeaderTime;
} }
quint64 ClientModel::getTotalBytesRecv() const quint64 ClientModel::getTotalBytesRecv() const
@ -337,6 +349,11 @@ static void BlockTipChanged(ClientModel *clientmodel, bool initialSync, const CB
int64_t& nLastUpdateNotification = fHeader ? nLastHeaderTipUpdateNotification : nLastBlockTipUpdateNotification; int64_t& nLastUpdateNotification = fHeader ? nLastHeaderTipUpdateNotification : nLastBlockTipUpdateNotification;
if (fHeader) {
// cache best headers time and height to reduce future cs_main locks
clientmodel->cachedBestHeaderHeight = pIndex->nHeight;
clientmodel->cachedBestHeaderTime = pIndex->GetBlockTime();
}
// if we are in-sync, update the UI regardless of last update time // if we are in-sync, update the UI regardless of last update time
if (!initialSync || now - nLastUpdateNotification > MODEL_UPDATE_DELAY) { if (!initialSync || now - nLastUpdateNotification > MODEL_UPDATE_DELAY) {
//pass a async signal to the UI thread //pass a async signal to the UI thread

View File

@ -9,6 +9,8 @@
#include <QObject> #include <QObject>
#include <QDateTime> #include <QDateTime>
#include <atomic>
class AddressTableModel; class AddressTableModel;
class BanTableModel; class BanTableModel;
class OptionsModel; class OptionsModel;
@ -84,6 +86,10 @@ public:
QString formatClientStartupTime() const; QString formatClientStartupTime() const;
QString dataDir() const; QString dataDir() const;
// caches for the best header
mutable std::atomic<int> cachedBestHeaderHeight;
mutable std::atomic<int64_t> cachedBestHeaderTime;
private: private:
OptionsModel *optionsModel; OptionsModel *optionsModel;
PeerTableModel *peerTableModel; PeerTableModel *peerTableModel;