Files
benilla-octo/crates
gromandClaude Opus 5 112647b919 perf(ui): the handler profiler names the worst single call, not only the mean
`WOW_UI_HANDLERS` ranked handlers by self time over the window, which is the
right ranking for what costs framerate and the wrong one for what costs a
frame. A handler that stalls once every four seconds has a mean near zero over
five hundred frames and never reaches the table at all.

The player's session had a 15-28 ms tick in nearly every five-second window —
one dropped frame every few seconds, which is the kind of thing a player
reports as "it hitches" and no average will ever show. The table said
`UIParent:OnUpdate 60.8 us/f` and nothing about it.

So each slot keeps its costliest single call, the table gets a `worst` column,
and the handlers whose worst call cost a frame are listed again underneath —
but only the ones the table left out, so the block says something new or
nothing. `tick_bench` prints the same ranking.

It names the stall on the first run, offline, in this interface:

```
15768.7 us once  (self 17080.8 us over 240 calls)  pfQuestMapTracker:OnUpdate
12339.4 us once  (self 13042.0 us over 240 calls)  AceEvent20Frame:OnUpdate
 5380.9 us once  (self 16166.0 us over 240 calls)  pfQuest\quest.lua:348:OnUpdate
```

92% of the tracker's whole cost over 240 frames is one call. Both of the top
two are steady per-frame allocators, which made the collector the first
suspect; the bench's own heap line refutes it — 222.8 MB live against 29.1
kB/frame of churn is ~131 s between 200%-pause cycles, not the ~4 s the stall
recurs on. What the per-binding bill says is in there instead: one `pcall` of
7.5 ms, and `frame:GetLeft` at 92 us a call, which is a layout resolve against
a dirty graph.

`measure.sh` comes with it. The set of instruments worth arming for a play-test
is long enough that a run with one of them missing is normal, and such a run
looks exactly like a run that found nothing — the session this column came from
was missing `WOW_SYSTEM_TIMING`, so it could say what the UI cost and not what
the frame cost. The script arms the set and prints what it armed.

The test asserts the property the column exists for and not a duration: a
handler called ten times for 50k iterations each outranks one called once for
150k by self time, and the second still has the larger worst call.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn
2026-10-20 06:19:20 -06:00
..