Skip to content

perf: build nothing while the window is hidden - #24

Merged
tkc merged 1 commit into
mainfrom
skip-draw-when-hidden
Sep 10, 2026
Merged

perf: build nothing while the window is hidden#24
tkc merged 1 commit into
mainfrom
skip-draw-when-hidden

Conversation

@tkc

@tkc tkc commented Sep 10, 2026

Copy link
Copy Markdown
Owner

What

WindowEvent::Occluded was never handled. When the window is fully covered by another window, macOS refuses to hand out a drawable, and draw() only discovered that at the last step:

  1. lay out the sidebar, the grid and the bottom bar
  2. prepare (glyphon: shaping + glyph atlas upload)
  3. get_current_texture — fails

Steps 1 and 2 were done and thrown away, once every 32 ms, for as long as the window stayed hidden.

Evidence

TERMIT_FRAME_LOG=1 on a window launched behind other windows:

描く面を取れなかった: 間に合わず=0 隠れて=26 作り直し=0

The counters reset every second, so that is 26 discarded frames per second.

--bench now reports the build phase too, so the discarded work can be priced:

size build prepare discarded per frame
1280x800 (7,661 cells) 0.02 ms 0.55 ms 0.57 ms
1920x1200 (17,150 cells) 0.03 ms 1.17 ms 1.20 ms

At 26–31 frames a second that is 1.5–2% of a core, 3–4% on a large window, spent on frames that cannot be shown.

Limits, stated honestly

This is the per-frame cost times the observed rate — not a before/after CPU measurement. A window cannot be occluded on command from a shell on this machine (synthetic input and window activation are not permitted), so the occluded state cannot be reproduced for an A/B. docs/performance.md 7.11 says so in the same words.

Change

  • State.occluded, set from WindowEvent::Occluded; redraw on un-occlude (no timer — winit reports it).
  • Early return at the top of draw() while occluded, keeping needs_redraw set.
  • The get_current_texture back-off stays as the fallback, so a wrong occlusion report cannot freeze the window permanently.
  • --bench: build-phase column.
  • docs/performance.md 7.11.

Test

cargo test — 200 pass. cargo clippy --all-targets -- -D warnings — clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GvMacYD6T9EoWqc7C247Hr

When the window is fully covered, macOS refuses to hand out a drawable.
draw() only found out at step 3 (get_current_texture); steps 1 and 2 --
laying out the sidebar, the grid and the bottom bar, then glyphon's
prepare -- had already run and were thrown away, 26 times a second on the
32ms retry.

Track WindowEvent::Occluded, which was not handled at all, and return at
the top of draw() while hidden. Redraw when the window comes back; no
timer is needed, winit tells us.

--bench now also reports the build phase, which is the part the skip
saves alongside prepare: 0.57ms per discarded frame at 1280x800 and
1.20ms at 1920x1200, so 1.5-4% of a core was going into frames that
could not be shown. That figure is the cost per frame times the observed
rate, not a before/after measurement: this machine cannot occlude a
window on command, so the honest limits are written down in
docs/performance.md 7.11.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GvMacYD6T9EoWqc7C247Hr
@tkc
tkc merged commit 4841425 into main Sep 10, 2026
1 check passed
@tkc
tkc deleted the skip-draw-when-hidden branch September 10, 2026 01:39
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