Record the step 5 result: hints skip the room ask, and the far pin is not the cost
Measured at a888717 and at the new f6242aa on wip/hint-first, with the inset experiment recorded as tested and rejected. The plan is now review, render and land.
This commit is contained in:
1 parent
1ef31bc9e7
commit
e4fada298d
2 files changed
+242
-124
No files matched your search
@@ -7,6 +7,78 @@ must outlive it (settled design, the measurement method) is already in
|
||||
`docs/LAYOUT.md`, and the current plan is in `docs/HANDOFF.md`. Commit ids
|
||||
are in `/home/bob/repos/iris-layout-experiment` unless said otherwise.
|
||||
|
||||
## What the step 5 measurements found (planner, 2026-09-19)
|
||||
|
||||
Re-measured `a888717` first: every number in the handoff's table reproduced
|
||||
exactly (342/288, 118/95, 3/3, 1, 44/13 at seed 1; 1278/982, 429/366 at
|
||||
seed 13), so the table was trusted. What the counters said beyond it:
|
||||
|
||||
- **Most redraws never reached the reuse check.** `many` at seed 1 made 118
|
||||
draws and only 78 reuse attempts, 4 of them rejected; the other draws
|
||||
came from `retained_answer` failing before `try_reuse` ran. Mechanism: a
|
||||
share child is asked in the room and then in its slot, one record holds
|
||||
one answer, and each ask overwrites it -- so the room ask finds the slot
|
||||
answer (pinned to the slot's length) and the slot ask finds the room
|
||||
answer, and each draws. Every ancestor redraw pays it twice per share
|
||||
child, multiplied down nested shares.
|
||||
- **#18 avoided the room ask where a hint or rule gave the length.** Its
|
||||
`Span` called `painter.known_len` first; `3091fb8` dropped that with the
|
||||
offer machinery. Restored at `f6242aa` as `Painter::size_hint`, which now
|
||||
resolves a fraction against the asking widget's frame (it returned the raw
|
||||
rule before, which no caller had noticed because its one caller read
|
||||
`px`) and pins that frame where it did. `Scroll`, `Masked`, a `Stack`
|
||||
without a sizing child and the fixture's `Branch` gained `LEFTOVER`
|
||||
hints. A hinted child is asked once, in its slot; a hinted share with no
|
||||
room is never asked and is undrawn. Cost (draws / distinct, depth 8):
|
||||
seed 1 cold 264/232, many 41/41, size 3/3, scroll 1, resize 36/13; seed
|
||||
13 cold 758/627, many 16/16, resize nothing. `many` is at its floor:
|
||||
every draw is a marked widget or the parent one deferred to. Cold layout
|
||||
of 400 trees at depth 5 is byte-identical to `a888717` (the new
|
||||
`tests/layout_dump.rs`), and the three long fuzzers agree.
|
||||
- **What is left is reported shares.** With hints in, the hottest widget
|
||||
in seed 1's resize frame is a `Span` drawn 8 times, two more drawn 4 and a
|
||||
`Branch` drawn 4: a span whose children report `leftover` has no hint, is
|
||||
asked in the room and in its slot, and both draw because the room drawing
|
||||
divided the room (`far` read, pinned to that length). Under the root's
|
||||
resize redraw that is 2 per level of nesting. It is also the whole of
|
||||
cold's draws over its distinct count.
|
||||
|
||||
The design that removes it, not implemented: keep two answers on the
|
||||
record, the room answer from a measuring ask and the slot answer from the
|
||||
placing ask, with the drawing belonging to the placing ask. A measuring
|
||||
ask (`Painter::measure`, a new call the parent makes explicitly, so
|
||||
"which ask is the measurement" is stated rather than inferred) reuses the
|
||||
room answer when its holds contain the room and touches no drawing;
|
||||
otherwise it draws in the room and records the answer as the room's. The
|
||||
placing ask is `widget_at` as now. A local redraw of a twice-asked child
|
||||
re-asks both questions, marks the parent if either answer moved, and puts
|
||||
the drawing back otherwise -- which also retires `re_asked`'s deferral.
|
||||
The cost is a second `Option<(Size, LayoutHolds)>` on `ActiveData` and a
|
||||
measuring path through `draw_inner` that skips `try_reuse` and `relocate`.
|
||||
This is the one-record-two-questions bookkeeping the earlier plans died
|
||||
of, made explicit at the call site instead of recovered from the ask; it
|
||||
is worth doing only once an app screen shows reported shares nested
|
||||
under a resize, and that screen should be measured first.
|
||||
- **Dropping the span's `far` pin does nothing** (`wip/inset` at `5b181bc`,
|
||||
pushed, one commit over `f6242aa`): `Part::Of` replaced by
|
||||
`Part::Inset { lead, trail }` in window lengths, an exact `in_parent` arm
|
||||
for a pixel inset (the range moved by the pixels, `Holds::longer_by`) and
|
||||
a pinned own length plus a window range for one with a fraction, `Pad`
|
||||
speaking it, and `Span` reading `extent_len` only with shares or in the
|
||||
negative direction. Suite, oracle and clippy green; counters identical to
|
||||
`f6242aa` at every phase of both seeds. Why: a symbolic pin survives a
|
||||
resize because every ask box is symbolically stable across one -- the
|
||||
viewport a scroll asks its content in is `rel 1`, a slot is a sum of
|
||||
pixel answers, a stack's sized part is an answer -- so the pin only fails
|
||||
where an answer changed, which is a real relayout. The worker's "44 to
|
||||
20" at `a888717` was a deliberately unsound read, and what it saved was
|
||||
share spans reusing the drawing that divided the room in the slot that
|
||||
is narrower: wrong layout, not spared work. Not to be repeated; the
|
||||
branch is evidence.
|
||||
- **The frame pin on a rule that is a fraction costs nothing** to speak of:
|
||||
`reuse outside: a frame length` is 3 of 264 cold draws at seed 1 and 1 of
|
||||
758 at seed 13. Dropped from the plan.
|
||||
|
||||
## What making the frame a length found (worker, 2026-09-19)
|
||||
|
||||
Step 2 of the handoff, implemented over `0ef87eb` in
|
||||
|
||||
Reference in new issue
Block a user