Repository navigation
bench: decode beside a display loop on the Mac (#81) - #161
Merged
Merged
Conversation
Issue #81 asks how long a decode takes inside a client's display loop, where a real client draws the last picture at the screen's refresh while frames arrive at a stream's pace. The benchmark app's Mac front-end gains a -display mode: a borderless window over a screen, a CVDisplayLink and a CAMetalLayer draw the last decoded picture at the refresh, while emberwave (RGB texture, Y/Cb/Cr textures) and HEVC (NV12) decode as frames arrive. Each way is also run without the loop in the same run, so the loop's cost is a difference within one run. The report adds the time from a frame's arrival until the display presented it (the drawable's presentedTime). The stream runs at 59.5 frames a second so that frames drift across the refreshes, as a stream's do against a display; frames locked to the refresh would all show one latency. CADisplayLink stays at 60 Hz on a 120 Hz screen for an app that is not in front, so a CVDisplayLink is used. The shared benchmark code gains only a PictureSink type, a settable frame rate in FrameClock, and entry points that decode an HEVC stream paced with a sink; the iOS app is not changed. Claude-Session: https://claude.ai/code/session_019fJGoCTvP5e7n599q3ZQ42
BENCHMARKS.md gets the measurements of 2026-11-06: decode times with and without a display loop at 60 and 120 Hz, and the time to the screen, for emberwave and HEVC. D72 records how the loop is built and why, and what was not done (the iPhone half, a real client's pipeline). The READMEs' roadmap notes the Mac's half of #81 as done. Claude-Session: https://claude.ai/code/session_019fJGoCTvP5e7n599q3ZQ42
A review of the display-loop benchmark found that the mean time to the screen of the 60 Hz loop depends on the run's start phase, that the rows without a loop ran in an application with no window on the screen, and that nothing stopped a run on a sleeping or locked screen from printing rows as if it had drawn. The program now times whole beats of its stream's drift against a 60 Hz loop (119 frames, 357 for a run), keeps a black window on the screen for the rows without a loop, keeps the displays awake, and stops where the window never reaches the screen. The display link's statistics start with the first timed frame, frames not drawn are counted as timed offers minus timed draws, frames the display never presented are counted, and the HEVC stream's failures other than "unavailable" fail the run. FrameClock takes its rate as an argument. The docs say what the first runs were and what is to be repeated. Claude-Session: https://claude.ai/code/session_019fJGoCTvP5e7n599q3ZQ42
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.
Purpose
Issue #81 asks how long a decode takes while a client's display loop draws at the screen's refresh. This is the Mac's half; the iPhone's needs the phone.
Changes
scripts/bench_app_on_mac.sh -display(and-short): a borderless window covers a screen while aCVDisplayLinkand aCAMetalLayerdraw the last decoded picture at the refresh. emberwave (Y, Cb, Cr textures and RGB) and HEVC (NV12) decode as frames arrive, each way without the loop and with a 60 and a 120 Hz loop in the same run. The report adds the time from a frame's arrival until the display presented it.PictureSinktype, arateargument forFrameClockand entry points that decode a prepared HEVC stream paced with a sink. The iOS app's behaviour does not change; the shared files typecheck for the iOS Simulator, andscripts/bench_app_on_mac.sh -autorunpasses.Result (two runs of the first version, M3 Max, 2026-11-06)
Limits
Testing
scripts/bench_app_on_mac.sh -displaytwice, in full, with the first version;-display -shortwhile developing;scripts/bench_app_on_mac.sh -autorunafter the last commit. CI builds the iOS app and runs-autorun; it never runs-display.Refs #81