Skip to content

quest: drop ui-frame-rate, whose 25 fps was Xvfb's presentation - #96

Merged
kixelated merged 6 commits into
mainfrom
quest/m0/ui-frame-rate
Nov 7, 2026
Merged

kixelated merged 6 commits into
mainfrom
quest/m0/ui-frame-rate

Conversation

@kixelated

@kixelated kixelated commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

Problem

quest/m0/ui-frame-rate.md came from moq-dev/studio#85, which measured the UI at about 25 fps (40 ms a frame) under Xvfb and guessed the UI waits on engine.state while the program renders. The quest asked to profile on a real display and under Xvfb, fix the cause, or delete the quest if the wait is only Xvfb's.

Approach

Profiled with temporary instrumentation (not committed): every engine.state lock timed per thread, the program's lock hold and Compositor::render, the encoders' program copy, and a patched egui-wgpu timing the three steps eframe counts as "vsync" (get_current_texture, Queue::submit, Queue::present). Release build with openh264, the scene from #85 (color, image, HTML overlay) and a plain one-color scene, at 1920x1080 30 fps. "Loaded" means every effect forced on (the program on air, Health unhealthy, a take every 2 s) and a recording running, as #85's worst case.

The wait is Xvfb's presentation. Under Xvfb, Queue::present takes 40 to 110 ms a frame and is the whole UI frame. On a real compositor the same build draws at the display's 60 Hz under the same load, with present under 0.4 ms and no lock waits. So this PR deletes the quest.

Xvfb, nixos (RTX 3070 Ti, load average ~30 from other work)

Run UI frame present UI CPU UI lock wait per frame (max) program render program copy
plain scene 50.7-58.5 ms 47.7-55.5 ms 2.4 ms 0.00 ms (0.3) 18.3-23.6 ms
#85 scene 58.5-62.5 ms 55.1-58.5 ms 2.7-2.8 ms 0.11 ms (30) 22.8-24.6 ms
#85 scene, loaded 101-117 ms 95-109 ms 5.7-7.8 ms 1.0-2.9 ms (10) 39.8-45.4 ms 91 ms

vkcube alone under the same Xvfb takes 83 ms a frame at 1440x900 (18 ms at 500x500), so Xvfb's present is this slow without the studio. #85's 40 ms was the same present on a less loaded host; its "UI CPU under 2 ms" already included the lock waits.

Headless sway, nixos2 (RTX 2070 renders the studio, 1600x1000 at 60 Hz)

Run UI frame (max) present UI CPU UI lock wait per frame (max) program render (max) program copy
plain, Intel composites 16.72 ms (16.8) 0.06-0.10 ms 0.6-0.9 ms 0.00 ms (0.2) 0.10 ms (0.5)
#85 scene, loaded, Intel composites 16.73 ms (16.8) 0.07-0.28 ms 0.9-1.0 ms 0.00 ms (0.2) 0.19 ms (0.9) 5.6 ms
#85 scene, loaded, RTX 2070 composites 17.5-17.6 ms (19.2) 0.3-0.4 ms 0.8-0.9 ms 0.00 ms (0.1) 0.18 ms (0.4) 6.7 ms
  • Where the UI thread waits: on the display, nowhere else. The UI takes engine.state 8 times a frame and waits a total of 0.00 ms on average.
  • GPU queue contention: none on a real compositor; the UI's submit takes 0.04-0.07 ms and the program's render 0.1-0.2 ms. Under Xvfb the program's render slows from 0.2 ms to 18-45 ms and its copy from 6 ms to 91 ms, consistent with Xvfb's present stalling the queue both share.
  • The 17.5 ms frames with sway compositing on the RTX 2070 are sway's pacing: vkcube there also runs about 6% slower than with the Intel compositing.
  • Program render time and encoder load: unchanged, since no code changes.

What was not measured

  • A physical display (KMS page flips): neither host has one attached. Headless sway paces its output on a 60 Hz timer and composites on the GPU, which is the closest available.
  • GNOME: mutter --headless's virtual monitor stopped sending frame callbacks after the first ~16 frames on both hosts, stalling vkcube too, also when a screencast read the monitor. nixos2's live GNOME session has no monitor to draw on.
  • A real X server (Xorg with the NVIDIA driver), macOS, and Windows.

Impact

  • None for users: this only deletes the quest and its link in quest/m0/README.md.
  • Public API and wire: no change.

Alternatives

  • Taking engine.state only to copy what a frame draws, or moving the compositor's submit off the UI's path, as the quest suggested: the UI's lock waits are ~0 on a real compositor, so neither would change its frame rate.
  • Committing the instrumentation: it patches egui-wgpu and adds per-frame timing for a one-off question; the Output panel already shows the program's encoder work.

Choices made without asking:

  • Measured the real-compositor case on headless sway rather than GNOME, since headless mutter never paced a client (above).

Follow-ups

  • Agents measuring the UI keep reaching for Xvfb, which on these NVIDIA hosts presents at 12-25 fps whatever the app does. A line in AGENTS.md pointing UI frame-time measurements at a headless Wayland compositor (WLR_BACKENDS=headless sway) would stop the next one; it is a rule change, so it is the maintainer's call.

Review

Codex (gpt-6.1-sol, medium effort), round 1 of session 01a1b6ec-74ca-7820-ad02-d905bfa588f5, reviewed head eef09ce550f65f8ff7c586dc5c12b0dc94512473 against origin/main a8ca56f: no findings.

Checks: quest check passed at this head. just ci was not run locally: the diff only deletes quest Markdown, which quest check is the only check to read; CI's Check runs just ci on the ready PR.

(Written by Claude Opus 5.5)

🤖 Generated with Claude Code

Quest-Claim: 50ca11f50a96e3d8
@pullfrog

pullfrog Bot commented Nov 7, 2026

Copy link
Copy Markdown

Pullfrog  | Review this ➔

@kixelated kixelated changed the title The UI keeps its frame rate while the program renders quest: drop ui-frame-rate, whose 25 fps was Xvfb's presentation Nov 7, 2026
@kixelated
kixelated marked this pull request as ready for review November 7, 2026 16:52
@coderabbitai

coderabbitai Bot commented Nov 7, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 58 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: e9825d93-d242-4c9a-9ea3-d5ded47ceea0
Commits

Reviewing files that changed from the base of the PR and between 47c4b3d and 1192e66.

Files selected for processing: 3

  • AGENTS.md
  • quest/m0/README.md
  • quest/m0/ui-frame-rate.md
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@kixelated

Copy link
Copy Markdown
Contributor Author

Pick (/quest-complete, maintainer away under /afk, recommended option): ✅ Merge, deleting the quest: the 25 fps was Xvfb's present, and the UI holds 60 fps under headless sway. Took the suggested AGENTS.md line, so agents measure UI frame time under headless sway instead of Xvfb (two in a row used Xvfb). Merged main.

(Written by Claude Opus 5.5)

@kixelated kixelated left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Automated review by review (OpenAI)

Reviewed head 111838161f801c790566b25a169260a601f889a5 against base a461c842511aa3664af049ff78209854e28378cf.

No actionable findings. The deleted quest explicitly permits closure when profiling attributes the wait to Xvfb. The reported presentation timings, vkcube control and loaded headless-sway results support that explanation without requiring a speculative locking refactor. The parent link is removed, and the new measurement guidance targets the environment that confounded the original observation.

Direction: removing an unsupported implementation task is simpler than changing runtime scheduling without evidence of a studio bottleneck.

Verification limits: GitHub-only documentation review, including the originating PR, repository guidance and pinned quest context as source. I did not run quest context, tests or profiling. The temporary instrumentation is not committed; measurements are not independently verified. The comparison uses different hosts, and physical-display and other-platform behavior remains unmeasured as disclosed in the PR.

(Written by review (OpenAI))

@kixelated
kixelated merged commit 57eeb09 into main Nov 7, 2026
3 checks passed
@kixelated
kixelated deleted the quest/m0/ui-frame-rate branch November 7, 2026 17:30
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.

1 participant