renderer, termio: count each surface's thread wakes by source

Merged
LA
2d ago
+58-0

Summary

ghostty_surface_render_counters gains seven fields at the end of the struct. They count each surface's thread wakes by source:

  • renderer thread: the wakeup async, the draw-now async, and the cursor blink, animation and scrollback-compression timer fires
  • termio thread: the wakeup async, and its timer fires (resize coalesce, synchronized-output reset, selection scroll)

Each count is one relaxed atomic add in a callback that already runs. No behavior changes.

Why

cmux keeps hidden terminals live (its warm set). On cmux24, 24 busy hidden terminals at a warm cap of 25 woke the app 181.8 times a second, against 76.9 at a cap of 8. None of those wakeups were on the main thread.

cmux's own counters show that its output path already runs once per hidden output batch. So the remaining cost, about 2.4-3.4 wakeups a second while idle plus 3-4 per batch for each live hidden terminal, is on the surface's own threads. These counts name the source, per surface, so a cmux test can bound it exactly (cmux SWITCH FRAMES, "hidden output" row).

Base

This is based on release/cmux-9ce9b7d0-e2 (34e73ba8b), the cmux pin, so that one GhosttyNextKit pin bump takes only this change. The struct grows at its end; the existing fields keep their offsets.

Test plan

  • Fork CI builds the xcframework for this PR.
  • The cmux red test (branch fix/hidden-terminal-wakeups) reads these counts for live hidden surfaces.

Autofix with [code]smith
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Adds per-surface thread wake counters to ghostty_surface_render_counters so a cmux test can bound the cost of keeping hidden terminals alive. Each counter is a relaxed atomic add in an existing callback; no behavior changes.

  • Renderer thread counters: wakeup async, draw-now async, and cursor blink, animation, and scrollback-compression timer fires.
  • Termio thread counters: wakeup async and timer fires (resize coalesce, synchronized-output reset, selection scroll).