thread_pool: skip spurious wakeups in hill-climb monitor

pthread_cond_timedwait can return early due to spurious wakeups.
When this happens the throughput delta covers a shorter-than-expected
interval, producing an artificially low sample.  Two consecutive
spurious wakes would cause the EMA to decline twice, crossing the
decline_threshold and triggering a false direction reversal — the
monitor would shrink the pool when throughput was actually stable.

Record the wall-clock time before sleeping and discard any sample
where the elapsed time is less than half the target interval.  The
_stop check runs first so shutdown is never delayed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Antonio S. Musumeci 2026-04-10 17:32:51 -04:00
parent c43a14f269
commit 159a5c7b71

View file

@ -566,6 +566,7 @@ ThreadPool::monitor_routine(void *arg_)
{
// Sleep for one sample interval, but wake immediately if the
// destructor signals _monitor_cond.
std::uint64_t t0 = _now_usecs();
{
struct timespec abs_ts;
clock_gettime(CLOCK_MONOTONIC,&abs_ts);
@ -587,6 +588,14 @@ ThreadPool::monitor_routine(void *arg_)
if(btp->_stop.load(std::memory_order_acquire))
break;
// Skip spurious wakeups. A short interval yields an
// artificially low throughput delta that would cause the EMA
// to decline and potentially trigger a false direction
// reversal in the hill-climber.
std::uint64_t elapsed = _now_usecs() - t0;
if(elapsed < (std::uint64_t)interval / 2)
continue;
std::uint64_t completed = btp->_tasks_completed.load(std::memory_order_relaxed);
std::uint64_t raw_throughput = completed - prev_completed;
prev_completed = completed;