Skip to content

Commit 1052b09

Browse files
committed
Merge #19011: Reduce cs_main lock accumulation during GUI startup
386ec19 Reduce cs_main lock accumulation during GUI startup (Jonas Schnelli) d42cb79 Optionally populate BlockAndHeaderTipInfo during AppInitMain (Jonas Schnelli) b354a14 Add BlockAndHeaderTipInfo to the node interface/appInit (Jonas Schnelli) 25e1d0b RPCConsole, take initial chaintip data as parameter (Jonas Schnelli) Pull request description: During the GUI startup, there is currently an accumulation of cs_main locks due to setting initial chain state values at multiple locations (in the GUI main thread). This PR tries to cache the initial chain state (tip height, tip time, best header, etc.) short after loading the blockindex. The cached values are then used instead of fetching them again (and thus locking `cs_main`) during setting the client model. This should fix the initial GUI blocking often experienced during or short after the splashscreen. On mac, best tested together with #19007. ACKs for top commit: promag: Code review ACK 386ec19. ryanofsky: Code review ACK 386ec19. Just rebased since last review due to conflicts Tree-SHA512: caccca05360e6dc0c3aade5e7ed24be513607821a8bd6612d0337259304ab772799fb2d707a0d7c7e50fbff4bd394354643fd0aeaa3bb55960ccc28562f4763d
2 parents 8a85377 + 386ec19 commit 1052b09

File tree

11 files changed

+49
-24
lines changed

11 files changed

+49
-24
lines changed

src/init.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <index/blockfilterindex.h>
2525
#include <index/txindex.h>
2626
#include <interfaces/chain.h>
27+
#include <interfaces/node.h>
2728
#include <key.h>
2829
#include <miner.h>
2930
#include <net.h>
@@ -1242,7 +1243,7 @@ bool AppInitLockDataDirectory()
12421243
return true;
12431244
}
12441245

1245-
bool AppInitMain(const util::Ref& context, NodeContext& node)
1246+
bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
12461247
{
12471248
const CChainParams& chainparams = Params();
12481249
// ********************************************************* Step 4a: application initialization
@@ -1877,6 +1878,15 @@ bool AppInitMain(const util::Ref& context, NodeContext& node)
18771878
LOCK(cs_main);
18781879
LogPrintf("block tree size = %u\n", chainman.BlockIndex().size());
18791880
chain_active_height = chainman.ActiveChain().Height();
1881+
if (tip_info) {
1882+
tip_info->block_height = chain_active_height;
1883+
tip_info->block_time = chainman.ActiveChain().Tip() ? chainman.ActiveChain().Tip()->GetBlockTime() : Params().GenesisBlock().GetBlockTime();
1884+
tip_info->verification_progress = GuessVerificationProgress(Params().TxData(), chainman.ActiveChain().Tip());
1885+
}
1886+
if (tip_info && ::pindexBestHeader) {
1887+
tip_info->header_height = ::pindexBestHeader->nHeight;
1888+
tip_info->header_time = ::pindexBestHeader->GetBlockTime();
1889+
}
18801890
}
18811891
LogPrintf("nBestHeight = %d\n", chain_active_height);
18821892

src/init.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
#include <util/system.h>
1212

1313
struct NodeContext;
14+
namespace interfaces {
15+
struct BlockAndHeaderTipInfo;
16+
}
1417
namespace boost {
1518
class thread_group;
1619
} // namespace boost
@@ -54,7 +57,7 @@ bool AppInitLockDataDirectory();
5457
* @note This should only be done after daemonization. Call Shutdown() if this function fails.
5558
* @pre Parameters should be parsed and config file should be read, AppInitLockDataDirectory should have been called.
5659
*/
57-
bool AppInitMain(const util::Ref& context, NodeContext& node);
60+
bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info = nullptr);
5861

5962
/**
6063
* Register all arguments with the ArgsManager

src/interfaces/node.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,10 @@ class NodeImpl : public Node
8080
return AppInitBasicSetup() && AppInitParameterInteraction() && AppInitSanityChecks() &&
8181
AppInitLockDataDirectory();
8282
}
83-
bool appInitMain() override
83+
bool appInitMain(interfaces::BlockAndHeaderTipInfo* tip_info) override
8484
{
8585
m_context->chain = MakeChain(*m_context);
86-
return AppInitMain(m_context_ref, *m_context);
86+
return AppInitMain(m_context_ref, *m_context, tip_info);
8787
}
8888
void appShutdown() override
8989
{

src/interfaces/node.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,16 @@ class Handler;
3939
class Wallet;
4040
struct BlockTip;
4141

42+
//! Block and header tip information
43+
struct BlockAndHeaderTipInfo
44+
{
45+
int block_height;
46+
int64_t block_time;
47+
int header_height;
48+
int64_t header_time;
49+
double verification_progress;
50+
};
51+
4252
//! Top-level interface for a bitcoin node (bitcoind process).
4353
class Node
4454
{
@@ -96,7 +106,7 @@ class Node
96106
virtual bool baseInitialize() = 0;
97107

98108
//! Start node.
99-
virtual bool appInitMain() = 0;
109+
virtual bool appInitMain(interfaces::BlockAndHeaderTipInfo* tip_info = nullptr) = 0;
100110

101111
//! Stop node.
102112
virtual void appShutdown() = 0;

src/qt/bitcoin.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ static void RegisterMetaTypes()
8181

8282
qRegisterMetaType<std::function<void()>>("std::function<void()>");
8383
qRegisterMetaType<QMessageBox::Icon>("QMessageBox::Icon");
84+
qRegisterMetaType<interfaces::BlockAndHeaderTipInfo>("interfaces::BlockAndHeaderTipInfo");
8485
}
8586

8687
static QString GetLangTerritory()
@@ -164,8 +165,9 @@ void BitcoinCore::initialize()
164165
{
165166
qDebug() << __func__ << ": Running initialization in thread";
166167
util::ThreadRename("qt-init");
167-
bool rv = m_node.appInitMain();
168-
Q_EMIT initializeResult(rv);
168+
interfaces::BlockAndHeaderTipInfo tip_info;
169+
bool rv = m_node.appInitMain(&tip_info);
170+
Q_EMIT initializeResult(rv, tip_info);
169171
} catch (const std::exception& e) {
170172
handleRunawayException(&e);
171173
} catch (...) {
@@ -342,7 +344,7 @@ void BitcoinApplication::requestShutdown()
342344
Q_EMIT requestedShutdown();
343345
}
344346

345-
void BitcoinApplication::initializeResult(bool success)
347+
void BitcoinApplication::initializeResult(bool success, interfaces::BlockAndHeaderTipInfo tip_info)
346348
{
347349
qDebug() << __func__ << ": Initialization result: " << success;
348350
// Set exit result.
@@ -352,7 +354,7 @@ void BitcoinApplication::initializeResult(bool success)
352354
// Log this only after AppInitMain finishes, as then logging setup is guaranteed complete
353355
qInfo() << "Platform customization:" << platformStyle->getName();
354356
clientModel = new ClientModel(m_node, optionsModel);
355-
window->setClientModel(clientModel);
357+
window->setClientModel(clientModel, &tip_info);
356358
#ifdef ENABLE_WALLET
357359
if (WalletModel::isWalletEnabled()) {
358360
m_wallet_controller = new WalletController(*clientModel, platformStyle, this);

src/qt/bitcoin.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#include <QApplication>
1313
#include <memory>
1414

15+
#include <interfaces/node.h>
16+
1517
class BitcoinGUI;
1618
class ClientModel;
1719
class NetworkStyle;
@@ -21,10 +23,6 @@ class PlatformStyle;
2123
class WalletController;
2224
class WalletModel;
2325

24-
namespace interfaces {
25-
class Handler;
26-
class Node;
27-
} // namespace interfaces
2826

2927
/** Class encapsulating Bitcoin Core startup and shutdown.
3028
* Allows running startup and shutdown in a different thread from the UI thread.
@@ -40,7 +38,7 @@ public Q_SLOTS:
4038
void shutdown();
4139

4240
Q_SIGNALS:
43-
void initializeResult(bool success);
41+
void initializeResult(bool success, interfaces::BlockAndHeaderTipInfo tip_info);
4442
void shutdownResult();
4543
void runawayException(const QString &message);
4644

@@ -91,7 +89,7 @@ class BitcoinApplication: public QApplication
9189
void setupPlatformStyle();
9290

9391
public Q_SLOTS:
94-
void initializeResult(bool success);
92+
void initializeResult(bool success, interfaces::BlockAndHeaderTipInfo tip_info);
9593
void shutdownResult();
9694
/// Handle runaway exceptions. Shows a message box with the problem and quits the program.
9795
void handleRunawayException(const QString &message);

src/qt/bitcoingui.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,7 @@ void BitcoinGUI::createToolBars()
574574
}
575575
}
576576

577-
void BitcoinGUI::setClientModel(ClientModel *_clientModel)
577+
void BitcoinGUI::setClientModel(ClientModel *_clientModel, interfaces::BlockAndHeaderTipInfo* tip_info)
578578
{
579579
this->clientModel = _clientModel;
580580
if(_clientModel)
@@ -588,8 +588,8 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel)
588588
connect(_clientModel, &ClientModel::numConnectionsChanged, this, &BitcoinGUI::setNumConnections);
589589
connect(_clientModel, &ClientModel::networkActiveChanged, this, &BitcoinGUI::setNetworkActive);
590590

591-
modalOverlay->setKnownBestHeight(_clientModel->getHeaderTipHeight(), QDateTime::fromTime_t(_clientModel->getHeaderTipTime()));
592-
setNumBlocks(m_node.getNumBlocks(), QDateTime::fromTime_t(m_node.getLastBlockTime()), m_node.getVerificationProgress(), false, SynchronizationState::INIT_DOWNLOAD);
591+
modalOverlay->setKnownBestHeight(tip_info->header_height, QDateTime::fromTime_t(tip_info->header_time));
592+
setNumBlocks(tip_info->block_height, QDateTime::fromTime_t(tip_info->block_time), tip_info->verification_progress, false, SynchronizationState::INIT_DOWNLOAD);
593593
connect(_clientModel, &ClientModel::numBlocksChanged, this, &BitcoinGUI::setNumBlocks);
594594

595595
// Receive and report messages from client model
@@ -600,7 +600,7 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel)
600600
// Show progress dialog
601601
connect(_clientModel, &ClientModel::showProgress, this, &BitcoinGUI::showProgress);
602602

603-
rpcConsole->setClientModel(_clientModel);
603+
rpcConsole->setClientModel(_clientModel, tip_info->block_height, tip_info->block_time, tip_info->verification_progress);
604604

605605
updateProxyIcon();
606606

src/qt/bitcoingui.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ enum class SynchronizationState;
4343
namespace interfaces {
4444
class Handler;
4545
class Node;
46+
struct BlockAndHeaderTipInfo;
4647
}
4748

4849
QT_BEGIN_NAMESPACE
@@ -75,7 +76,7 @@ class BitcoinGUI : public QMainWindow
7576
/** Set the client model.
7677
The client model represents the part of the core that communicates with the P2P network, and is wallet-agnostic.
7778
*/
78-
void setClientModel(ClientModel *clientModel);
79+
void setClientModel(ClientModel *clientModel = nullptr, interfaces::BlockAndHeaderTipInfo* tip_info = nullptr);
7980
#ifdef ENABLE_WALLET
8081
void setWalletController(WalletController* wallet_controller);
8182
#endif

src/qt/rpcconsole.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ bool RPCConsole::eventFilter(QObject* obj, QEvent *event)
556556
return QWidget::eventFilter(obj, event);
557557
}
558558

559-
void RPCConsole::setClientModel(ClientModel *model)
559+
void RPCConsole::setClientModel(ClientModel *model, int bestblock_height, int64_t bestblock_date, double verification_progress)
560560
{
561561
clientModel = model;
562562

@@ -576,13 +576,13 @@ void RPCConsole::setClientModel(ClientModel *model)
576576
setNumConnections(model->getNumConnections());
577577
connect(model, &ClientModel::numConnectionsChanged, this, &RPCConsole::setNumConnections);
578578

579-
interfaces::Node& node = clientModel->node();
580-
setNumBlocks(node.getNumBlocks(), QDateTime::fromTime_t(node.getLastBlockTime()), node.getVerificationProgress(), false);
579+
setNumBlocks(bestblock_height, QDateTime::fromTime_t(bestblock_date), verification_progress, false);
581580
connect(model, &ClientModel::numBlocksChanged, this, &RPCConsole::setNumBlocks);
582581

583582
updateNetworkState();
584583
connect(model, &ClientModel::networkActiveChanged, this, &RPCConsole::setNetworkActive);
585584

585+
interfaces::Node& node = clientModel->node();
586586
updateTrafficStats(node.getTotalBytesRecv(), node.getTotalBytesSent());
587587
connect(model, &ClientModel::bytesChanged, this, &RPCConsole::updateTrafficStats);
588588

src/qt/rpcconsole.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class RPCConsole: public QWidget
4646
return RPCParseCommandLine(&node, strResult, strCommand, true, pstrFilteredOut, wallet_model);
4747
}
4848

49-
void setClientModel(ClientModel *model);
49+
void setClientModel(ClientModel *model = nullptr, int bestblock_height = 0, int64_t bestblock_date = 0, double verification_progress = 0.0);
5050
void addWallet(WalletModel * const walletModel);
5151
void removeWallet(WalletModel* const walletModel);
5252

0 commit comments

Comments
 (0)