Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

146. A HUD shows where the frame went

Date: 2026-08-19

Status

Accepted. Extends ADR-0101’s hud with the four stages a frame is made of.

Context

The showcase spent a month painting at 10–15 ms with nothing on screen moving. The HUD said paint 12.4 ms, which was true and useless: a total says a frame is slow and says nothing about which part of it is. Finding the answer took a purpose-built probe, a counter compiled into the renderer and two rounds of guessing — and the answer, when it came, was that the style cache had stopped hitting the day scroll shipped (ADR-0142).

A number on screen would have said so on the first frame.

Decision

Four more readings — build, style, layout, raster — and one word for the set of them.

hud readings="stages"
host.overlay(Hud.stages(), Corner.BOTTOM_END);

The launcher’s painter takes five nanoTime readings and hands the four intervals to the frame ring, which keeps them in the same 60-slot window as the paint time. Ungated by log level, for the reason ADR-0101 gives about the rate itself: a diagnostic you have to reconfigure the process to see is one nobody looks at, and five timestamps against a frame costing hundreds of microseconds is not a cost worth a branch.

The four do not add up to paint, and are not asserted to. The hit-test capture and the frame’s own setup are in the total and in none of the stages — neither large enough to name nor zero. Making them add up would mean either a fifth “other” reading nobody can act on, or moving work around to make a display tidy.

Two decimals for a stage, one for a total. 0.0 ms cannot be told from a stage that is not running, and telling those apart is the whole use of a breakdown. Three ranks in the stylesheet — the rate bright, the total dim, the stages dimmer and one size down — because six equally bright numbers on one plate read as a wall.

Consequences

The showcase turns it on, so the thing that gets looked at is the thing that would have shown the defect.

A raster that jumps when nothing moved is a buffer that stopped retaining, not a scene that got harder — the damage-tracking half of ADR-0072 made visible for the first time.

A build above zero is a widget dirtying itself every frame, which is the one failure this catalog has repeatedly produced and never had a reading for.

FrameStats grew four methods with a default of zero, so a source that does not measure the stages — every one but the frame loop’s own — reports zero rather than lying. A HUD with no loop over it still draws dashes, which is the existing distinction between “not measured” and “measured as nothing” (ADR-0101).