Document coalesced resize layout
This commit is contained in:
1 parent
986f98380d
commit
974d6c7a52
2 files changed
+59
-39
No files matched your search
@@ -9,7 +9,7 @@ Canonical `main` is **`ca2b4b2`** (#17, the headless rig). Sixteen slices are
|
||||
in.
|
||||
|
||||
**#18 `split/18-position-chain`** is open and finished apart from one decision:
|
||||
worktree `/home/bob/repos/iris-pr18`, head `480f0bc`, sixteen commits,
|
||||
worktree `/home/bob/repos/iris-pr18`, head `82fa6c1`, seventeen commits,
|
||||
workspace tests passing, fmt and clippy clean. It is LAYOUT.md §2's position chain, generalised
|
||||
to boxes. `/home/bob/repos/ai-app-2` is on `rustify`, worktree clean.
|
||||
|
||||
@@ -183,24 +183,51 @@ IRIS_PHASE=resize IRIS_DEPTH=8 IRIS_FRAMES=1000 \
|
||||
--test layout_diagnostics -- --ignored --nocapture
|
||||
```
|
||||
|
||||
The first depth-8 resize run makes the amplification concrete. A 260-widget
|
||||
tree has 215 active widgets, but a resize averages 1,395 widget draws, 913
|
||||
`82fa6c1` adds targeted tracing to the same feature. Call
|
||||
`layout_diagnostics::trace_widget(id)` before a frame; `take().traces()` then
|
||||
returns the selected widgets' ordered draw requests and pixel boxes, reuse
|
||||
outcomes, placements, hints, size reads and reported sizes, and text widths.
|
||||
The selection is a set, survives `take()`, and is removed with
|
||||
`untrace_widget` or `clear_traced_widgets`. This replaces temporary
|
||||
text-specific logging without imposing anything on normal builds.
|
||||
|
||||
The first depth-8 resize run made the amplification concrete. A 260-widget
|
||||
tree has 215 active widgets, but a resize averaged 1,395 widget draws, 913
|
||||
placement calls, 1,313 reads of drawn sizes and 34,844 primitive writes. Only
|
||||
12 distinct text widgets render, yet they render and reshape 282 times per
|
||||
frame with no shape-cache hits. Text rendering accounts for 11.6 of 13.2 ms,
|
||||
including 9.9 ms shaping and 1.7 ms placing glyphs. The hottest two text
|
||||
widgets each draw 96 times per frame at 22 distinct widths across two resize
|
||||
frames, below nested `Span`, `Aligned`, `Scroll`, `Pad`, and `SetSize`
|
||||
ancestors. This identifies repeated constraint discovery, rather than resize
|
||||
marking (0.001 ms), as the next subject; it does not yet choose between
|
||||
per-axis retained size validity and coalescing the resize dependency frontier.
|
||||
12 distinct text widgets rendered, yet they rendered and reshaped 282 times
|
||||
per frame with no shape-cache hits. Text rendering accounted for 11.6 of 13.2
|
||||
ms, including 9.9 ms shaping and 1.7 ms placing glyphs. The hottest two text
|
||||
widgets each drew 96 times below nested `Span`, `Aligned`, `Scroll`, `Pad`, and
|
||||
`SetSize` ancestors.
|
||||
|
||||
Tracing one of them showed that 96 was two multipliers, not 96 necessary
|
||||
layout iterations. One traversal of the nested positioning chain shaped it 32
|
||||
times at 12 widths; three resize-dependent descendants then caused that whole
|
||||
traversal to run three times through the same highest size reader. Resize
|
||||
marking had queued each pixel reader independently, and each leaf discovered
|
||||
and redrew the same reader path in turn.
|
||||
|
||||
`82fa6c1` coalesces that frontier by marking every resize-dependent leaf and
|
||||
its size-reader chain first, then settling the shallowest shared reader once.
|
||||
Ordinary content and size changes remain deepest-first. On the same depth-8
|
||||
load, an actual resize now averages about 694 widget draws, 435 placement
|
||||
calls, 649 drawn-size reads, 15,343 primitive writes, and 116 text shapes; the
|
||||
hottest texts draw 32 times. Instrumented layout is about 5.5 ms instead of
|
||||
13.2 ms. An uninstrumented 1,000-frame resize run measured a 5.61 ms median,
|
||||
60.79B instructions total (60.8M/frame), and 23.85B cycles. This is about 58%
|
||||
fewer instructions than the roughly 138M/frame #18 path before coalescing,
|
||||
but still about 1.8x the old 3.14 ms resize median. The remaining multiplier
|
||||
is within one constraint traversal, so per-axis retained size validity is now
|
||||
the useful next question. Re-sending the existing output size also no longer
|
||||
starts a resize.
|
||||
|
||||
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
|
||||
sweep passed every transition through seed 59 and now gets past the former
|
||||
scroll failure at seed 52; at seed 60 it reaches the already-documented
|
||||
iterative wrapping-text defect, differing by 0.00003 px after `SwapForThree`.
|
||||
fixes. The regular cold-layout equivalence suite and the ignored 100-seed
|
||||
sweep pass. The latter previously stopped at seed 60 on `140.0` versus
|
||||
`139.99996948242188`: exactly two `f32` ULPs from an equivalent composition
|
||||
order, not a visible layout difference. The oracle now keeps draw presence
|
||||
exact and allows at most four ULPs per pixel coordinate.
|
||||
|
||||
The branches are invariants rather than widget exceptions:
|
||||
|
||||
@@ -211,9 +238,10 @@ The branches are invariants rather than widget exceptions:
|
||||
condition the discarded `/tmp/escalate.patch` missed on resize.
|
||||
- Dirty widgets settle deepest-first. A changed size queues only its immediate
|
||||
reader; propagation stops as soon as a reader's own answer stays unchanged.
|
||||
During an output resize, the resize condition stays live until these updates
|
||||
finish, so an `Aligned` ancestor chooses the new child box before a
|
||||
pixel-dependent descendant draws in it.
|
||||
Output resize is the distinct invariant: all pixel-dependent leaves and
|
||||
their reader chains are marked together, then shared reader roots settle
|
||||
shallowest-first under the new output. This both chooses the parent box
|
||||
before drawing its descendant and coalesces overlapping resize paths.
|
||||
- A span measures an unknown child in the part of its axis still available,
|
||||
rather than giving every child the whole container and immediately taking
|
||||
most of it away. This is the archive's faster shape, recreated on the current
|
||||
|
||||
Reference in new issue
Block a user