Service platform tasks due within a frame early - #29
Merged
Merged
Conversation
Both run loops slept a full frame period whenever the next engine task was due sooner, adding up to a frame of latency. Wake at the task's due time instead, with a 1ms floor. Idle behaviour (empty queue) is unchanged, and vsync is still aligned to frame boundaries by the embedder. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F1bgmVQVQTHUQpQtBbFw6t
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Both
FlutterWindowrun loops (theTimerpath andrun() async) slept for at least a full frame period, even whenprocessMessages()said the next engine task was due sooner. That delayed such tasks by up to one frame, about 16.7 ms at 60 Hz. The C++ reference runner in flutter-embedded-linux sleeps onlywait_durationin that case.This change wakes the loop when that task is due, with a 1 ms floor.
CPU impact should be negligible:
processMessages()returnsInt64.maxand both loops still wake once per frame, as before.TaskRunner::ProcessTasks(), thendispatchEvent(), which doesn't block (Waylandpollwith timeout 0,XPendingon X11,sd_event_run/uv_runwith no wait on DRM).dispatchEvent()also delivers vsync, butVsyncWaiter::NotifyVsynconly fires if the engine requested a frame, and the frame start is still aligned to the next vsync boundary. Frames can't render faster than the refresh rate.Timer path: the timer callback already sets
fireDateto delay the next fire. CFRunLoop honours anyfireDateset during the callout that's later than the fire that just happened, so setting an earlier one (now + max(wait, 1 ms)) works the same way.The existing behaviour of sleeping longer than a frame when the next task is further out is unchanged.
Independent of #28 and merges cleanly with it. Built with
swift build --target FlutterSwift; not yet tested on target hardware.🤖 Generated with Claude Code
https://claude.ai/code/session_01F1bgmVQVQTHUQpQtBbFw6t