mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-06-09 06:31:41 +02:00
Merge #19011: Reduce cs_main lock accumulation during GUI startup
386ec192a57b76492125d691ceda1b4aa832312e Reduce cs_main lock accumulation during GUI startup (Jonas Schnelli) d42cb790687788c78aa2f0c1988238ab52050782 Optionally populate BlockAndHeaderTipInfo during AppInitMain (Jonas Schnelli) b354a1480abbd71fb7fb82c39c81ea0644bbfce4 Add BlockAndHeaderTipInfo to the node interface/appInit (Jonas Schnelli) 25e1d0bf417237caa5d36b4e757f29e6c8be8aad 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 386ec192a57b76492125d691ceda1b4aa832312e. ryanofsky: Code review ACK 386ec192a57b76492125d691ceda1b4aa832312e. Just rebased since last review due to conflicts Tree-SHA512: caccca05360e6dc0c3aade5e7ed24be513607821a8bd6612d0337259304ab772799fb2d707a0d7c7e50fbff4bd394354643fd0aeaa3bb55960ccc28562f4763d
This commit is contained in:
commit
1052b09031
12
src/init.cpp
12
src/init.cpp
@ -24,6 +24,7 @@
|
|||||||
#include <index/blockfilterindex.h>
|
#include <index/blockfilterindex.h>
|
||||||
#include <index/txindex.h>
|
#include <index/txindex.h>
|
||||||
#include <interfaces/chain.h>
|
#include <interfaces/chain.h>
|
||||||
|
#include <interfaces/node.h>
|
||||||
#include <key.h>
|
#include <key.h>
|
||||||
#include <miner.h>
|
#include <miner.h>
|
||||||
#include <net.h>
|
#include <net.h>
|
||||||
@ -1242,7 +1243,7 @@ bool AppInitLockDataDirectory()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AppInitMain(const util::Ref& context, NodeContext& node)
|
bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||||
{
|
{
|
||||||
const CChainParams& chainparams = Params();
|
const CChainParams& chainparams = Params();
|
||||||
// ********************************************************* Step 4a: application initialization
|
// ********************************************************* Step 4a: application initialization
|
||||||
@ -1877,6 +1878,15 @@ bool AppInitMain(const util::Ref& context, NodeContext& node)
|
|||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
LogPrintf("block tree size = %u\n", chainman.BlockIndex().size());
|
LogPrintf("block tree size = %u\n", chainman.BlockIndex().size());
|
||||||
chain_active_height = chainman.ActiveChain().Height();
|
chain_active_height = chainman.ActiveChain().Height();
|
||||||
|
if (tip_info) {
|
||||||
|
tip_info->block_height = chain_active_height;
|
||||||
|
tip_info->block_time = chainman.ActiveChain().Tip() ? chainman.ActiveChain().Tip()->GetBlockTime() : Params().GenesisBlock().GetBlockTime();
|
||||||
|
tip_info->verification_progress = GuessVerificationProgress(Params().TxData(), chainman.ActiveChain().Tip());
|
||||||
|
}
|
||||||
|
if (tip_info && ::pindexBestHeader) {
|
||||||
|
tip_info->header_height = ::pindexBestHeader->nHeight;
|
||||||
|
tip_info->header_time = ::pindexBestHeader->GetBlockTime();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
LogPrintf("nBestHeight = %d\n", chain_active_height);
|
LogPrintf("nBestHeight = %d\n", chain_active_height);
|
||||||
|
|
||||||
|
@ -11,6 +11,9 @@
|
|||||||
#include <util/system.h>
|
#include <util/system.h>
|
||||||
|
|
||||||
struct NodeContext;
|
struct NodeContext;
|
||||||
|
namespace interfaces {
|
||||||
|
struct BlockAndHeaderTipInfo;
|
||||||
|
}
|
||||||
namespace boost {
|
namespace boost {
|
||||||
class thread_group;
|
class thread_group;
|
||||||
} // namespace boost
|
} // namespace boost
|
||||||
@ -54,7 +57,7 @@ bool AppInitLockDataDirectory();
|
|||||||
* @note This should only be done after daemonization. Call Shutdown() if this function fails.
|
* @note This should only be done after daemonization. Call Shutdown() if this function fails.
|
||||||
* @pre Parameters should be parsed and config file should be read, AppInitLockDataDirectory should have been called.
|
* @pre Parameters should be parsed and config file should be read, AppInitLockDataDirectory should have been called.
|
||||||
*/
|
*/
|
||||||
bool AppInitMain(const util::Ref& context, NodeContext& node);
|
bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info = nullptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register all arguments with the ArgsManager
|
* Register all arguments with the ArgsManager
|
||||||
|
@ -80,10 +80,10 @@ public:
|
|||||||
return AppInitBasicSetup() && AppInitParameterInteraction() && AppInitSanityChecks() &&
|
return AppInitBasicSetup() && AppInitParameterInteraction() && AppInitSanityChecks() &&
|
||||||
AppInitLockDataDirectory();
|
AppInitLockDataDirectory();
|
||||||
}
|
}
|
||||||
bool appInitMain() override
|
bool appInitMain(interfaces::BlockAndHeaderTipInfo* tip_info) override
|
||||||
{
|
{
|
||||||
m_context->chain = MakeChain(*m_context);
|
m_context->chain = MakeChain(*m_context);
|
||||||
return AppInitMain(m_context_ref, *m_context);
|
return AppInitMain(m_context_ref, *m_context, tip_info);
|
||||||
}
|
}
|
||||||
void appShutdown() override
|
void appShutdown() override
|
||||||
{
|
{
|
||||||
|
@ -39,6 +39,16 @@ class Handler;
|
|||||||
class Wallet;
|
class Wallet;
|
||||||
struct BlockTip;
|
struct BlockTip;
|
||||||
|
|
||||||
|
//! Block and header tip information
|
||||||
|
struct BlockAndHeaderTipInfo
|
||||||
|
{
|
||||||
|
int block_height;
|
||||||
|
int64_t block_time;
|
||||||
|
int header_height;
|
||||||
|
int64_t header_time;
|
||||||
|
double verification_progress;
|
||||||
|
};
|
||||||
|
|
||||||
//! Top-level interface for a bitcoin node (bitcoind process).
|
//! Top-level interface for a bitcoin node (bitcoind process).
|
||||||
class Node
|
class Node
|
||||||
{
|
{
|
||||||
@ -96,7 +106,7 @@ public:
|
|||||||
virtual bool baseInitialize() = 0;
|
virtual bool baseInitialize() = 0;
|
||||||
|
|
||||||
//! Start node.
|
//! Start node.
|
||||||
virtual bool appInitMain() = 0;
|
virtual bool appInitMain(interfaces::BlockAndHeaderTipInfo* tip_info = nullptr) = 0;
|
||||||
|
|
||||||
//! Stop node.
|
//! Stop node.
|
||||||
virtual void appShutdown() = 0;
|
virtual void appShutdown() = 0;
|
||||||
|
@ -81,6 +81,7 @@ static void RegisterMetaTypes()
|
|||||||
|
|
||||||
qRegisterMetaType<std::function<void()>>("std::function<void()>");
|
qRegisterMetaType<std::function<void()>>("std::function<void()>");
|
||||||
qRegisterMetaType<QMessageBox::Icon>("QMessageBox::Icon");
|
qRegisterMetaType<QMessageBox::Icon>("QMessageBox::Icon");
|
||||||
|
qRegisterMetaType<interfaces::BlockAndHeaderTipInfo>("interfaces::BlockAndHeaderTipInfo");
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString GetLangTerritory()
|
static QString GetLangTerritory()
|
||||||
@ -164,8 +165,9 @@ void BitcoinCore::initialize()
|
|||||||
{
|
{
|
||||||
qDebug() << __func__ << ": Running initialization in thread";
|
qDebug() << __func__ << ": Running initialization in thread";
|
||||||
util::ThreadRename("qt-init");
|
util::ThreadRename("qt-init");
|
||||||
bool rv = m_node.appInitMain();
|
interfaces::BlockAndHeaderTipInfo tip_info;
|
||||||
Q_EMIT initializeResult(rv);
|
bool rv = m_node.appInitMain(&tip_info);
|
||||||
|
Q_EMIT initializeResult(rv, tip_info);
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
handleRunawayException(&e);
|
handleRunawayException(&e);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
@ -342,7 +344,7 @@ void BitcoinApplication::requestShutdown()
|
|||||||
Q_EMIT requestedShutdown();
|
Q_EMIT requestedShutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BitcoinApplication::initializeResult(bool success)
|
void BitcoinApplication::initializeResult(bool success, interfaces::BlockAndHeaderTipInfo tip_info)
|
||||||
{
|
{
|
||||||
qDebug() << __func__ << ": Initialization result: " << success;
|
qDebug() << __func__ << ": Initialization result: " << success;
|
||||||
// Set exit result.
|
// Set exit result.
|
||||||
@ -352,7 +354,7 @@ void BitcoinApplication::initializeResult(bool success)
|
|||||||
// Log this only after AppInitMain finishes, as then logging setup is guaranteed complete
|
// Log this only after AppInitMain finishes, as then logging setup is guaranteed complete
|
||||||
qInfo() << "Platform customization:" << platformStyle->getName();
|
qInfo() << "Platform customization:" << platformStyle->getName();
|
||||||
clientModel = new ClientModel(m_node, optionsModel);
|
clientModel = new ClientModel(m_node, optionsModel);
|
||||||
window->setClientModel(clientModel);
|
window->setClientModel(clientModel, &tip_info);
|
||||||
#ifdef ENABLE_WALLET
|
#ifdef ENABLE_WALLET
|
||||||
if (WalletModel::isWalletEnabled()) {
|
if (WalletModel::isWalletEnabled()) {
|
||||||
m_wallet_controller = new WalletController(*clientModel, platformStyle, this);
|
m_wallet_controller = new WalletController(*clientModel, platformStyle, this);
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#include <interfaces/node.h>
|
||||||
|
|
||||||
class BitcoinGUI;
|
class BitcoinGUI;
|
||||||
class ClientModel;
|
class ClientModel;
|
||||||
class NetworkStyle;
|
class NetworkStyle;
|
||||||
@ -21,10 +23,6 @@ class PlatformStyle;
|
|||||||
class WalletController;
|
class WalletController;
|
||||||
class WalletModel;
|
class WalletModel;
|
||||||
|
|
||||||
namespace interfaces {
|
|
||||||
class Handler;
|
|
||||||
class Node;
|
|
||||||
} // namespace interfaces
|
|
||||||
|
|
||||||
/** Class encapsulating Bitcoin Core startup and shutdown.
|
/** Class encapsulating Bitcoin Core startup and shutdown.
|
||||||
* Allows running startup and shutdown in a different thread from the UI thread.
|
* Allows running startup and shutdown in a different thread from the UI thread.
|
||||||
@ -40,7 +38,7 @@ public Q_SLOTS:
|
|||||||
void shutdown();
|
void shutdown();
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void initializeResult(bool success);
|
void initializeResult(bool success, interfaces::BlockAndHeaderTipInfo tip_info);
|
||||||
void shutdownResult();
|
void shutdownResult();
|
||||||
void runawayException(const QString &message);
|
void runawayException(const QString &message);
|
||||||
|
|
||||||
@ -91,7 +89,7 @@ public:
|
|||||||
void setupPlatformStyle();
|
void setupPlatformStyle();
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void initializeResult(bool success);
|
void initializeResult(bool success, interfaces::BlockAndHeaderTipInfo tip_info);
|
||||||
void shutdownResult();
|
void shutdownResult();
|
||||||
/// Handle runaway exceptions. Shows a message box with the problem and quits the program.
|
/// Handle runaway exceptions. Shows a message box with the problem and quits the program.
|
||||||
void handleRunawayException(const QString &message);
|
void handleRunawayException(const QString &message);
|
||||||
|
@ -574,7 +574,7 @@ void BitcoinGUI::createToolBars()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BitcoinGUI::setClientModel(ClientModel *_clientModel)
|
void BitcoinGUI::setClientModel(ClientModel *_clientModel, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||||
{
|
{
|
||||||
this->clientModel = _clientModel;
|
this->clientModel = _clientModel;
|
||||||
if(_clientModel)
|
if(_clientModel)
|
||||||
@ -588,8 +588,8 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel)
|
|||||||
connect(_clientModel, &ClientModel::numConnectionsChanged, this, &BitcoinGUI::setNumConnections);
|
connect(_clientModel, &ClientModel::numConnectionsChanged, this, &BitcoinGUI::setNumConnections);
|
||||||
connect(_clientModel, &ClientModel::networkActiveChanged, this, &BitcoinGUI::setNetworkActive);
|
connect(_clientModel, &ClientModel::networkActiveChanged, this, &BitcoinGUI::setNetworkActive);
|
||||||
|
|
||||||
modalOverlay->setKnownBestHeight(_clientModel->getHeaderTipHeight(), QDateTime::fromTime_t(_clientModel->getHeaderTipTime()));
|
modalOverlay->setKnownBestHeight(tip_info->header_height, QDateTime::fromTime_t(tip_info->header_time));
|
||||||
setNumBlocks(m_node.getNumBlocks(), QDateTime::fromTime_t(m_node.getLastBlockTime()), m_node.getVerificationProgress(), false, SynchronizationState::INIT_DOWNLOAD);
|
setNumBlocks(tip_info->block_height, QDateTime::fromTime_t(tip_info->block_time), tip_info->verification_progress, false, SynchronizationState::INIT_DOWNLOAD);
|
||||||
connect(_clientModel, &ClientModel::numBlocksChanged, this, &BitcoinGUI::setNumBlocks);
|
connect(_clientModel, &ClientModel::numBlocksChanged, this, &BitcoinGUI::setNumBlocks);
|
||||||
|
|
||||||
// Receive and report messages from client model
|
// Receive and report messages from client model
|
||||||
@ -600,7 +600,7 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel)
|
|||||||
// Show progress dialog
|
// Show progress dialog
|
||||||
connect(_clientModel, &ClientModel::showProgress, this, &BitcoinGUI::showProgress);
|
connect(_clientModel, &ClientModel::showProgress, this, &BitcoinGUI::showProgress);
|
||||||
|
|
||||||
rpcConsole->setClientModel(_clientModel);
|
rpcConsole->setClientModel(_clientModel, tip_info->block_height, tip_info->block_time, tip_info->verification_progress);
|
||||||
|
|
||||||
updateProxyIcon();
|
updateProxyIcon();
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ enum class SynchronizationState;
|
|||||||
namespace interfaces {
|
namespace interfaces {
|
||||||
class Handler;
|
class Handler;
|
||||||
class Node;
|
class Node;
|
||||||
|
struct BlockAndHeaderTipInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
@ -75,7 +76,7 @@ public:
|
|||||||
/** Set the client model.
|
/** Set the client model.
|
||||||
The client model represents the part of the core that communicates with the P2P network, and is wallet-agnostic.
|
The client model represents the part of the core that communicates with the P2P network, and is wallet-agnostic.
|
||||||
*/
|
*/
|
||||||
void setClientModel(ClientModel *clientModel);
|
void setClientModel(ClientModel *clientModel = nullptr, interfaces::BlockAndHeaderTipInfo* tip_info = nullptr);
|
||||||
#ifdef ENABLE_WALLET
|
#ifdef ENABLE_WALLET
|
||||||
void setWalletController(WalletController* wallet_controller);
|
void setWalletController(WalletController* wallet_controller);
|
||||||
#endif
|
#endif
|
||||||
|
@ -556,7 +556,7 @@ bool RPCConsole::eventFilter(QObject* obj, QEvent *event)
|
|||||||
return QWidget::eventFilter(obj, event);
|
return QWidget::eventFilter(obj, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RPCConsole::setClientModel(ClientModel *model)
|
void RPCConsole::setClientModel(ClientModel *model, int bestblock_height, int64_t bestblock_date, double verification_progress)
|
||||||
{
|
{
|
||||||
clientModel = model;
|
clientModel = model;
|
||||||
|
|
||||||
@ -576,13 +576,13 @@ void RPCConsole::setClientModel(ClientModel *model)
|
|||||||
setNumConnections(model->getNumConnections());
|
setNumConnections(model->getNumConnections());
|
||||||
connect(model, &ClientModel::numConnectionsChanged, this, &RPCConsole::setNumConnections);
|
connect(model, &ClientModel::numConnectionsChanged, this, &RPCConsole::setNumConnections);
|
||||||
|
|
||||||
interfaces::Node& node = clientModel->node();
|
setNumBlocks(bestblock_height, QDateTime::fromTime_t(bestblock_date), verification_progress, false);
|
||||||
setNumBlocks(node.getNumBlocks(), QDateTime::fromTime_t(node.getLastBlockTime()), node.getVerificationProgress(), false);
|
|
||||||
connect(model, &ClientModel::numBlocksChanged, this, &RPCConsole::setNumBlocks);
|
connect(model, &ClientModel::numBlocksChanged, this, &RPCConsole::setNumBlocks);
|
||||||
|
|
||||||
updateNetworkState();
|
updateNetworkState();
|
||||||
connect(model, &ClientModel::networkActiveChanged, this, &RPCConsole::setNetworkActive);
|
connect(model, &ClientModel::networkActiveChanged, this, &RPCConsole::setNetworkActive);
|
||||||
|
|
||||||
|
interfaces::Node& node = clientModel->node();
|
||||||
updateTrafficStats(node.getTotalBytesRecv(), node.getTotalBytesSent());
|
updateTrafficStats(node.getTotalBytesRecv(), node.getTotalBytesSent());
|
||||||
connect(model, &ClientModel::bytesChanged, this, &RPCConsole::updateTrafficStats);
|
connect(model, &ClientModel::bytesChanged, this, &RPCConsole::updateTrafficStats);
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ public:
|
|||||||
return RPCParseCommandLine(&node, strResult, strCommand, true, pstrFilteredOut, wallet_model);
|
return RPCParseCommandLine(&node, strResult, strCommand, true, pstrFilteredOut, wallet_model);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setClientModel(ClientModel *model);
|
void setClientModel(ClientModel *model = nullptr, int bestblock_height = 0, int64_t bestblock_date = 0, double verification_progress = 0.0);
|
||||||
void addWallet(WalletModel * const walletModel);
|
void addWallet(WalletModel * const walletModel);
|
||||||
void removeWallet(WalletModel* const walletModel);
|
void removeWallet(WalletModel* const walletModel);
|
||||||
|
|
||||||
|
@ -67,6 +67,7 @@ void AppTests::appTests()
|
|||||||
return GetDataDir() / "blocks";
|
return GetDataDir() / "blocks";
|
||||||
}());
|
}());
|
||||||
|
|
||||||
|
qRegisterMetaType<interfaces::BlockAndHeaderTipInfo>("interfaces::BlockAndHeaderTipInfo");
|
||||||
m_app.parameterSetup();
|
m_app.parameterSetup();
|
||||||
m_app.createOptionsModel(true /* reset settings */);
|
m_app.createOptionsModel(true /* reset settings */);
|
||||||
QScopedPointer<const NetworkStyle> style(NetworkStyle::instantiate(Params().NetworkIDString()));
|
QScopedPointer<const NetworkStyle> style(NetworkStyle::instantiate(Params().NetworkIDString()));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user