perf(daemon): back off the monitor poll when idle
The daemon monitor thread drained output and then slept a fixed short interval on every tick, waking several times a second for the life of the node even long after startup, when the node emits almost nothing. Stopping it also meant waiting out the current sleep before it saw the stop flag. - The monitor now waits on a condition variable instead of a plain sleep, so a stop request wakes it immediately rather than after the interval. The stop flag is set under the monitor's mutex so the wake cannot be lost. - The poll interval stays fast for the first 30 s after the thread starts and for 3 s after any output, and otherwise doubles per idle tick up to a 500 ms cap. Any new output drops it straight back to fast, so responsiveness during startup, rescan and shutdown is unchanged while a quiet node is polled far less often. The interval choice is a pure function. Tests cover the interval function across the warmup window, the recent-data window, the reset on new output, the doubling, and the cap. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -6071,6 +6071,24 @@ void testOutputSinceAcrossTrim()
|
||||
EXPECT_TRUE(got.empty());
|
||||
}
|
||||
|
||||
void testNextMonitorInterval()
|
||||
{
|
||||
using dragonx::daemon::EmbeddedDaemon;
|
||||
using ms = std::chrono::milliseconds;
|
||||
const ms fast(100), cap(500);
|
||||
auto next = [&](ms cur, bool got, ms sinceStart, ms sinceData) {
|
||||
return EmbeddedDaemon::nextMonitorInterval(cur, got, sinceStart, sinceData, fast, cap);
|
||||
};
|
||||
EXPECT_TRUE(next(fast, false, ms(1000), ms(1000)) == fast); // first 30 s stay fast
|
||||
EXPECT_TRUE(next(cap, false, ms(29999), ms(60000)) == fast);
|
||||
EXPECT_TRUE(next(cap, false, ms(60000), ms(2999)) == fast); // recent data stays fast
|
||||
EXPECT_TRUE(next(cap, true, ms(60000), ms(60000)) == fast); // data resets
|
||||
EXPECT_TRUE(next(fast, false, ms(60000), ms(10000)) == ms(200)); // doubling
|
||||
EXPECT_TRUE(next(ms(200), false, ms(60000), ms(10000)) == ms(400));
|
||||
EXPECT_TRUE(next(ms(400), false, ms(60000), ms(10000)) == cap); // capped at 500
|
||||
EXPECT_TRUE(next(cap, false, ms(60000), ms(10000)) == cap);
|
||||
}
|
||||
|
||||
void testOutputWindowSaturation()
|
||||
{
|
||||
using dragonx::daemon::appendBounded;
|
||||
@@ -18694,6 +18712,7 @@ int main()
|
||||
testShouldConfirmStop();
|
||||
testOutputSinceAcrossTrim();
|
||||
testOutputWindowSaturation();
|
||||
testNextMonitorInterval();
|
||||
testOutputEndWatermarkReplay();
|
||||
testChooseDaemonStatus();
|
||||
testDaemonStopStringsTranslated();
|
||||
|
||||
Reference in New Issue
Block a user