diff --git a/docs/IRIS_EXTRACTION_HANDOFF.md b/docs/IRIS_EXTRACTION_HANDOFF.md index 13ae22f..ffb3ff1 100644 --- a/docs/IRIS_EXTRACTION_HANDOFF.md +++ b/docs/IRIS_EXTRACTION_HANDOFF.md @@ -144,6 +144,28 @@ now 2,117 cold, 1 for a leaf repaint, 11 for a scroll, and 3,139 for a resize five reference renders, resize render, and image-tab replay are byte-identical to the prior #18 head. +Those draw counts explain mechanism, not total layout cost. Before #16, +measurement was a separate operation: the cold and resize rows each made 839 +draws plus 489 size queries, 314 of which hit the size cache. Current sizing is +a draw, so its draw count includes the provisional work and cannot be compared +directly with the old draw count. Fresh release wall-time measurements put the +complete CPU layout cost in perspective: + +| per frame | before #16 | `84f589e` | +| --- | --- | --- | +| cold layout | 18.9 ms | 20.5–22.0 ms | +| repaint one leaf | below timer resolution | below timer resolution | +| scroll one scroller | below timer resolution | 0.002 ms | +| resize the output | 3.14 ms median | 12.3–13.4 ms median | + +Wall time moves with CPU frequency, so retained benchmark counters should +report CPU cycles or instructions as the deciding total, then separate widget +draws, size queries/probes, text shapes and primitive writes to explain it. A +whole-rig `perf stat` run, dominated by 100 resize frames, measured 13.76B +instructions current versus 3.56B before #16 (3.87x), consistent with the +resize wall-time gap. A follow-up rig should select one phase per invocation so +the hardware counters are phase-specific rather than inferred from that total. + The generated tree now includes `Aligned` with every meaningful per-axis alignment. That exposed two retained-layout ordering bugs which `84f589e` fixes. The regular cold-layout equivalence suite passes. The ignored 100-seed @@ -176,6 +198,14 @@ stale-size failure. Re-measuring the scroll subtree costs 11 draws rather than 1, but remains two orders of magnitude below the old 1,313 and follows the actual dependency invariant. +Do not restore the archive's old `DrawMode::Measure`. It skipped primitive and +retained-state writes while still walking widgets and shaping text, and once +improved a streamed-frame benchmark from 1.39 to 1.22 ms p50. Retained +placement later replaced it because a provisional draw is usually already +usable in its final box; measure-only mode would discard that useful output +and force another real traversal. The owner confirmed on 2026-09-14 that +direct placement is the intended path. + The remaining costs are: - **A container measures a child by drawing it in a box it will not keep.**