From 3e1ae5da7ce03a702b5a3836847b477585a8ad06 Mon Sep 17 00:00:00 2001 From: Mohamed Maatallah Date: Mon, 4 May 2026 20:47:44 +0100 Subject: [PATCH] Improve pulse sleep on busy servers (#4853) HandlePulseSleep now returns as soon as the sync thread queues work, instead of sleeping busy_sleep_time at the start of every pulse. Mitigates #4853 (high player count chat lag / packet loss with low CPU): with threadnet, the unconditional sleep could cap DoPulse while m_InResultQueue still grew. Replaced with a short 1ms polling loop that exits on PendingWorkToDo. Idle path unchanged (full idle_sleep_time). server_logic_fps_limit remains the hard cap. busy_sleep_time is no longer used on this path (option still parses). Test plan: code review only; needs 600+ player confirmation. --- Server/core/CServerImpl.cpp | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/Server/core/CServerImpl.cpp b/Server/core/CServerImpl.cpp index b868d455e02..11e46dc7b4e 100644 --- a/Server/core/CServerImpl.cpp +++ b/Server/core/CServerImpl.cpp @@ -544,21 +544,20 @@ void CServerImpl::HandlePulseSleep() return; } - CTickCount sleepLimit = CTickCount::Now() + CTickCount((long long)iSleepIdleMs); - - // Initial sleep period - int iInitialMs = std::min(iSleepIdleMs, iSleepBusyMs); - Sleep(Clamp(1, iInitialMs, 50)); - - // Remaining idle sleep period - int iFinalMs = Clamp(1, iSleepIdleMs - iInitialMs, 50); - for (int i = 0; i < iFinalMs; i++) + // Sleep up to idle_sleep_time in 1ms ticks, exiting the moment the sync + // thread queues a packet. The previous code did a blind Sleep for + // busy_sleep_time at the top of every pulse before checking the inbound + // queue, which capped logic FPS near 1000/busy_sleep_time on busy servers + // regardless of how full the queue already was (#4853). busy_sleep_time + // is no longer consulted on this path; server_logic_fps_limit is the + // existing knob for a hard cap. + const int iSleepMs = Clamp(0, iSleepIdleMs, 50); + const CTickCount deadline = CTickCount::Now() + CTickCount((long long)iSleepMs); + while (CTickCount::Now() < deadline) { if (m_pModManager->PendingWorkToDo()) - break; + return; Sleep(1); - if (CTickCount::Now() >= sleepLimit) - break; } }