perf(daemon): skip the UI-thread datadir lock wait
Starting the daemon polls for an already-running node holding the datadir, sleeping up to three 100 ms intervals to let a shutting-down node clear out. When a start runs on the UI thread, that is up to 300 ms of blocking sleep on the render thread. - The lock-wait poll count is now a parameter. A start invoked on the UI thread passes 0, which does a single check and never sleeps; every other caller keeps the three-poll wait. The default is unchanged, so background starts behave exactly as before. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+2
-1
@@ -5975,7 +5975,8 @@ bool App::startEmbeddedDaemon()
|
|||||||
|
|
||||||
// Only a process we actually launched starts a new story: a start that finds a node already running (and
|
// Only a process we actually launched starts a new story: a start that finds a node already running (and
|
||||||
// launches nothing) must not wipe what the tracker knows about that node from its debug.log.
|
// launches nothing) must not wipe what the tracker knows about that node from its debug.log.
|
||||||
const bool launched = daemon_controller_->start(settings_.get());
|
const bool launched = daemon_controller_->start(
|
||||||
|
settings_.get(), std::this_thread::get_id() == ui_thread_id_ ? 0 : daemon::EmbeddedDaemon::kDatadirLockWaitMaxPolls);
|
||||||
if (launched) resetDaemonBusy(); // a new process: whatever the last one was doing is over
|
if (launched) resetDaemonBusy(); // a new process: whatever the last one was doing is over
|
||||||
return launched;
|
return launched;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,10 +41,10 @@ void DaemonController::syncSettings(const config::Settings* settings)
|
|||||||
daemon_->setWalletFile(walletFile);
|
daemon_->setWalletFile(walletFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DaemonController::start(const config::Settings* settings)
|
bool DaemonController::start(const config::Settings* settings, int lockWaitPolls)
|
||||||
{
|
{
|
||||||
syncSettings(settings);
|
syncSettings(settings);
|
||||||
return daemon_->start();
|
return daemon_->start("", lockWaitPolls);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DaemonController::stop(int waitMs)
|
void DaemonController::stop(int waitMs)
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ public:
|
|||||||
void setStateCallback(StateCallback callback);
|
void setStateCallback(StateCallback callback);
|
||||||
void syncSettings(const config::Settings* settings);
|
void syncSettings(const config::Settings* settings);
|
||||||
|
|
||||||
bool start(const config::Settings* settings);
|
bool start(const config::Settings* settings, int lockWaitPolls = 3);
|
||||||
void stop(int waitMs);
|
void stop(int waitMs);
|
||||||
void markStopRequested();
|
void markStopRequested();
|
||||||
|
|
||||||
|
|||||||
@@ -505,7 +505,7 @@ static bool isPortInUse(int port)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmbeddedDaemon::start(const std::string& binary_path)
|
bool EmbeddedDaemon::start(const std::string& binary_path, int lockWaitPolls)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> life(lifecycle_mutex_);
|
std::lock_guard<std::mutex> life(lifecycle_mutex_);
|
||||||
|
|
||||||
@@ -564,11 +564,10 @@ bool EmbeddedDaemon::start(const std::string& binary_path)
|
|||||||
// skip_port_check_ / -datadir override) are exempt; they run their own datadir+port.
|
// skip_port_check_ / -datadir override) are exempt; they run their own datadir+port.
|
||||||
{
|
{
|
||||||
constexpr int kDatadirLockWaitPollMs = 100;
|
constexpr int kDatadirLockWaitPollMs = 100;
|
||||||
constexpr int kDatadirLockWaitMaxPolls = 3; // ~300ms total, breaks early on exit
|
|
||||||
bool stillRunning = false;
|
bool stillRunning = false;
|
||||||
if (!skip_port_check_ && override_datadir_.empty()) {
|
if (!skip_port_check_ && override_datadir_.empty()) {
|
||||||
stillRunning = isDaemonProcessRunning();
|
stillRunning = isDaemonProcessRunning();
|
||||||
for (int i = 0; stillRunning && i < kDatadirLockWaitMaxPolls; ++i) {
|
for (int i = 0; stillRunning && i < lockWaitPolls; ++i) {
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(kDatadirLockWaitPollMs));
|
std::this_thread::sleep_for(std::chrono::milliseconds(kDatadirLockWaitPollMs));
|
||||||
stillRunning = isDaemonProcessRunning();
|
stillRunning = isDaemonProcessRunning();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,10 @@ public:
|
|||||||
* @return true if process started successfully (or is already running); false while a stop
|
* @return true if process started successfully (or is already running); false while a stop
|
||||||
* session (beginStop() .. endStop()) is still in progress
|
* session (beginStop() .. endStop()) is still in progress
|
||||||
*/
|
*/
|
||||||
bool start(const std::string& binary_path = "");
|
static constexpr int kDatadirLockWaitMaxPolls = 3; // ~300ms total, breaks early on exit
|
||||||
|
|
||||||
|
/** @param lockWaitPolls max 100ms datadir-lock waits (0 = single check, never sleeps; for the UI thread) */
|
||||||
|
bool start(const std::string& binary_path = "", int lockWaitPolls = kDatadirLockWaitMaxPolls);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Stop the daemon process this object launched (never any other dragonxd)
|
* @brief Stop the daemon process this object launched (never any other dragonxd)
|
||||||
|
|||||||
Reference in New Issue
Block a user