Skip to content

Improve pulse sleep on busy servers (#4853)#4893

Open
Zephkek wants to merge 1 commit intomultitheftauto:masterfrom
Zephkek:fix/4853-pulse-sleep
Open

Improve pulse sleep on busy servers (#4853)#4893
Zephkek wants to merge 1 commit intomultitheftauto:masterfrom
Zephkek:fix/4853-pulse-sleep

Conversation

@Zephkek
Copy link
Copy Markdown
Contributor

@Zephkek Zephkek commented May 4, 2026

Summary

HandlePulseSleep returns as soon as the sync thread queues work, instead of always sleeping busy_sleep_time first.

Motivation (#4853)

With threadnet, the old path slept 20 ms (busy_sleep_time) before checking PendingWorkToDo. On busy servers (~600 players), this capped the logic thread while m_InResultQueue kept growing, causing chat lag/loss with CPU still moderate.

Change

Replaced the fixed top-of-pulse sleep + tail loop with a ~1 ms polling loop that returns the moment PendingWorkToDo() is true.

  • Idle: still uses full idle_sleep_time.
  • Busy: wakes as work arrives; server_logic_fps_limit is still the hard cap.
  • Removed the artificial 1 ms floor on the per-tick sleep at this call site; the effective minimum idle sleep is still bounded by CMainConfig::GetNoWorkToDoSleepTime() (currently floors at 10 ms).
  • busy_sleep_time is no longer used here. Option still parses and shows in perf info.

Test plan

Code review only (HandlePulseSleep, PendingWorkToDo, GetSleepIntervals). No 600-player test rig, so this needs operator confirmation that logic FPS isn't pinned near 1000 / busy_sleep_time under sustained inbound queue.

Checklist

HandlePulseSleep now returns as soon as the sync thread queues work,
instead of sleeping busy_sleep_time at the start of every pulse.

Mitigates multitheftauto#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.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adjusts the server main loop’s “pulse sleep” behavior so the logic thread can resume immediately when the sync/network thread has queued inbound work, avoiding a fixed pre-sleep that can bottleneck busy servers (per #4853).

Changes:

  • Replaced the prior “sleep busy_sleep_time first, then poll” pattern with a ~1ms polling loop up to idle_sleep_time, returning immediately when PendingWorkToDo() becomes true.
  • Removed consultation of busy_sleep_time in HandlePulseSleep() when server_logic_fps_limit is not set (FPS limiting remains handled by ApplyFrameRateLimit).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +552 to +555
// 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);
Copy link
Copy Markdown
Contributor Author

@Zephkek Zephkek May 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed the description, my bad copilot!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants