fix: improve unfocused window frame pacing - #3493
Conversation
Applies the review suggestions: both clamps now use the builtin max, and unfocusedSleepDuration is max(wait-elapsed-sleepOverhead, 0) without the separate branch. Extends the unit test to the boundaries that rewrite touches: elapsed+overhead exactly equal to wait, overhead larger than wait, and negative elapsed or overhead. Adds TestTimeSleepOvershoot behind the ebitengine_sleep_measurement build tag, so normal runs and CI skip its ~9s of sampling. It reports min/median/mean/p95/ max overshoot of time.Sleep(time.Second/60) over 500 samples, which is the measurement needed to judge whether compensating for the overshoot is warranted.
|
Both On your actual question — how much is That is ~10.4% of a 16.667ms frame. Feeding it through What that does not show: this is one run in a headless macOS sandbox (macOS 26.3, arm64), not an Ebitengine desktop session, and it says nothing about Windows or Linux scheduler behaviour. It establishes that the overshoot is big enough to matter at this frame budget. It does not demonstrate end-to-end that carrying the previous frame's overshoot forward restores 60 FPS in a real unfocused window — that needs a desktop-session measurement of the whole frame loop, ideally per OS. So: your skepticism about whether the overhead matters is answered, I think — 1.7ms out of 16.7ms is not noise. Whether this particular compensation is the right fix is a separate question, and I'd rather you have the numbers than my opinion. If you'd prefer the measurement test not live in the tree, I'll drop it and keep the numbers here in the thread. |
|
Thank you for elaborating. The overshoot seems a real. I suggest a way to record absolute time to wait like this in order to treat overheads correctly: const wait = time.Second / 60
now := time.Now()
if next := u.unfocusedNextWake.Add(wait); next.After(now) {
u.unfocusedNextWake = next
time.Sleep(time.Until(next))
} else {
// Fell behind, or just became unfocused: resync instead of chasing the past.
u.unfocusedNextWake = now
}Also, drop the tests. Especially, TestTimeSleepOvershoot was useful for this thread discussion, but we no longer need it. Thanks, |
What issue is this addressing?
In
internal/ui/ui_glfw.go, extract the unfocused sleep-budget calculation used byglfwBackend.updateGameand reduce its target interval from 1/60 second to the maintainer-suggested 1/120 second, continuing to subtract time already spent rendering the frame. Keep the existing focus detection, buffer swap, andtime.Sleepwiring intact, and skip sleeping when frame work has already consumed the shorter interval. Add a desktop-scoped unit test ininternal/ui/ui_glfw_test.gofor the duration calculation so boundary behavior is deterministic without relying on wall-clock timing or a live X server.Closes #3397
What type of issue is this addressing?
What this PR does | solves