`WOW_UI_TICK` measures `UiScript::tick`. `[sys-timing]` measures the Bevy system around it,
`ui_script::extract::tick_script`, which also runs the FontString measure round-trip and
`UiScript::resolve`. In a combat session the first read 38 ms/s — its lowest of the whole run —
while the second read 157 ms/s. Neither instrument was wrong, and 76% of the cost was in the space
between them, which is where the stutter players report lives.
`UiFrameCost` has carried the whole split since the hover recorder needed it, and `WOW_UI_COST=1`
prints it one line per frame: at this client's framerate, twenty thousand synchronous stderr writes
a minute from the thread being measured, which is the trap `sys_timing`'s header records costing
15 ms a frame. The split existed and was unusable in exactly the situation it was for.
So a window, and a worst column — a phase that is ruinous on one frame in a hundred has a mean near
nothing and is the only thing a player feels. `derives` is in the per-frame line because
`UiFrameCost::derives` is documented "expected zero", so a nonzero one names a whole-graph
re-derivation on sight.
`UiFrameCost::stamped` comes with it: the paint can return before any of its three arms wrote this
frame's phases, and a reader that cannot tell counts the previous frame twice.
Armed in ./measure.sh at 5 s, with the per-frame form left alone for the hover recorder.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn