Record exact layout equality and measured reuse improvements
This commit is contained in:
1 parent
0080bcbcba
commit
8f1a5e0a46
2 files changed
+64
-44
No files matched your search
+60
-43
@@ -376,19 +376,12 @@ boundaries through `through`, or make the grid floor everywhere.
|
||||
|
||||
### Where the residual comes from, and the snap
|
||||
|
||||
Both remaining steps are a symbolic region re-expressed by division rather
|
||||
than recomputed the way a cold draw computes it: `AxisRemap::Scale` divides
|
||||
to find a part's fraction of the old box, and `placed_box` scales a mixed
|
||||
`Len` by the alignment. Neither touches the threaded pixel chain, so every
|
||||
layout decision already agrees warm against cold; what differs is the
|
||||
composed position the shader and hit testing see, by up to 0.002 px.
|
||||
|
||||
Closing `Scale` exactly is possible: keep each primitive's region in its
|
||||
widget's own coordinates and recompose on a move with `within`, eight
|
||||
multiplies and no division against the current four divisions and twelve
|
||||
multiplies, exact by construction, sixteen bytes more per primitive. Closing
|
||||
the alignment one means resolving alignment in pixels, which costs the
|
||||
retained resize path. Neither is worth a thousandth of a pixel on its own.
|
||||
The `e44dea3` baseline's two-step allowance came from inverse remapping and
|
||||
alignment composed by different routes. The frame/extent continuation below
|
||||
retains local widget frames as well as local primitive coordinates, recomposes
|
||||
in the same order as a cold draw, and removes inverse remapping. Its oracle
|
||||
requires exact pixel-region equality. That experiment is not yet the pinned
|
||||
framework; the baseline's snap decision below still applies there.
|
||||
|
||||
Where it does matter is `snap_floor` in `prelude.wgsl`, which adds half a
|
||||
layout step before flooring: that absorbs float error and not a layout
|
||||
@@ -429,8 +422,8 @@ back.
|
||||
The original proposal was implemented by Claude as `5fcace1` on
|
||||
`wip/region-and-placement` in `/home/bob/repos/iris-pr18`. It kept the fraction
|
||||
reference stable but failed five layout cases and three draw-count cases.
|
||||
The correction is saved as `efb416b`, pushed to origin's
|
||||
`wip/region-and-placement`, in the isolated checkout
|
||||
The first correction is `efb416b`; the exact-recomposition continuation is
|
||||
`2ed5503`, pushed to origin's `wip/region-and-placement`, in the isolated checkout
|
||||
`/home/bob/repos/iris-layout-experiment`; **it is not on PR #18**. The original
|
||||
checkout is unchanged. Keep the experiment's build directory separate: Cargo
|
||||
can accept a different worktree's artifacts as fresh when a target directory
|
||||
@@ -475,34 +468,62 @@ placeholder zero answer became reusable once it was drawn during placement.
|
||||
and `adding_text_to_a_reverse_row_keeps_its_shared_height` reproduces the
|
||||
zero-height failure with a small tree.
|
||||
|
||||
Ordinary verification currently passes: formatting, workspace clippy with
|
||||
`layout-diagnostics`, all workspace tests (96 suite tests), and the fast
|
||||
generated cases. New regressions also inspect primitive coordinates for mixed
|
||||
frame/extent drawings, including a region node, and a content change after
|
||||
moving an inherited extent. A `tabs` resize from 1920x1200 to 900x1200 matches
|
||||
a cold 900x1200 screenshot with zero differing pixels. The release oracle
|
||||
passes 2000 seeds at depth 4 and 1000 seeds at depth 6 over all fifteen cases.
|
||||
The shrinker passes 400 seeds at depth 5, and the debug oracle passes 120
|
||||
seeds at depth 4 with assertions enabled.
|
||||
**Exact recomposition and reuse.** The continuation replaces `given_len` with
|
||||
`given_region`: each widget retains its original frame in its parent's
|
||||
coordinates. Moving a retained subtree replays those same local compositions,
|
||||
and stops at region nodes. `RegionRemap`, `AxisRemap`, and inverse division
|
||||
are gone. Fixed-pixel frames can now change size without forcing otherwise
|
||||
valid descendants to draw again. This adds 16 bytes per active widget; local
|
||||
primitive coordinates were already retained by `efb416b`.
|
||||
|
||||
The shared oracle now compares pixel regions with ordinary equality; there
|
||||
is no `AGREE_STEPS` allowance. Text publishes the range of its retained line
|
||||
breaks rather than narrowing that range to every later
|
||||
requested width. A layout with only explicit line breaks or no breaks holds
|
||||
at arbitrarily wider widths. New tests compare actual primitive and mask
|
||||
geometry and assert reuse for fixed-frame resizing and widening unwrapped
|
||||
text (including explicit newlines and empty content).
|
||||
|
||||
Ordinary verification passes: formatting, workspace clippy with
|
||||
`layout-diagnostics`, workspace tests, and the fast generated cases. The
|
||||
suite contains 98 tests. A `tabs` resize from 1920x1200
|
||||
to 900x1200 matches a cold 900x1200 screenshot with zero differing pixels.
|
||||
With exact equality, the final release oracle passes 2000 seeds at depth 4
|
||||
and 1000 seeds at depth 6, the shrinker passes 400 seeds at depth 5, and the
|
||||
debug oracle passes 120 seeds at depth 4 with assertions enabled. Every scan
|
||||
runs all fifteen scenarios. The fixed-frame reuse regression was also run
|
||||
against `efb416b`: it fails there with two child draws instead of one.
|
||||
|
||||
**Do not land this as a performance improvement.** The old stretching and
|
||||
wrapper reuse tests pass, and one numeric-size test improves from three draws
|
||||
to two. Cold work also improves against the broken `5fcace1` prototype: 604 to
|
||||
535 widget draws and 15,296 to 10,384 primitive writes on seed 1, depth 8.
|
||||
But against the last working `e44dea3`, the same rig does substantially more
|
||||
nested layout work:
|
||||
to two. The continuation reduces widget draws from `efb416b` by 6.9% cold,
|
||||
9.0% with many dirty widgets, 7.6% for a size change, and 8.7% for resize.
|
||||
Against the last working `e44dea3`, it still does substantially more nested
|
||||
layout work (seed 1, depth 8):
|
||||
|
||||
| phase | widget draws before | prototype | primitive writes before | prototype |
|
||||
| --- | ---: | ---: | ---: | ---: |
|
||||
| cold | 369 | 535 | 9635 | 10384 |
|
||||
| cold | 369 | 498 | 9635 | 9704 |
|
||||
| repaint | 1 | 1 | 1 | 1 |
|
||||
| many | 157 | 310 | 4721 | 6970 |
|
||||
| size | 16 | 275 | 106 | 5980 |
|
||||
| many | 157 | 282 | 4721 | 6398 |
|
||||
| size | 16 | 254 | 106 | 5725 |
|
||||
| scroll | 2 | 2 | 0 | 0 |
|
||||
| resize | 13 | 328.5 | 0 | 6721.5 |
|
||||
| resize | 13 | 300 | 0 | 6255 |
|
||||
|
||||
These are instrumented work counts, not elapsed-time speedups (50 frames per
|
||||
phase except cold, which is one; 578 generated widgets, 191 finally active).
|
||||
Uninstrumented release binaries, run directly with `perf stat -r 3 -e
|
||||
instructions:u`, also improve over `efb416b`: 2000 size-change frames fall
|
||||
from 14.3923B to 13.8914B instructions (3.5%); 2000 resize frames fall from
|
||||
16.9756B to 16.1331B (5.0%). These whole-process totals include fixture setup;
|
||||
reported run-to-run variation is at most 0.24%. The many-dirty workload falls
|
||||
from 16.7962B to 16.0030B instructions (4.7%, 2000 frames). Repaint and scroll
|
||||
keep their draw counts but incur small CPU increases: 0.8849B to 0.8913B
|
||||
(+0.7%) and 2.4332B to 2.4479B (+0.6%) over 100,000 frames each. These are
|
||||
CPU-work measurements, not phone frame times. Keeping measurement validity separate from final drawing validity
|
||||
and deferring to an already dirty parent were also tried; neither improved
|
||||
this rig's draw counts, so those changes were removed.
|
||||
|
||||
Raw placement reads in containers and repeated offer/placement evaluations
|
||||
remain conservative. Retaining local coordinates also costs memory per
|
||||
primitive. The experiment demonstrates selective reuse with one `Widget::draw`
|
||||
@@ -591,17 +612,13 @@ cold reach every length by the same expression.
|
||||
|
||||
### What the fuzzers tolerate
|
||||
|
||||
`AGREE_STEPS` in `tests/scenario/mod.rs` is **2**, and both steps are
|
||||
positions. One is a box centred in a fraction of its parent against the
|
||||
same box centred in its own pixels, 0.001 px on a handful of seeds. The
|
||||
other is `AxisRemap::Scale` re-expressing a part as a fraction of a box that
|
||||
changed length; one step fails the 400-seed shrinker on `resize-size`,
|
||||
seeds 384 and 162, by 0.002 px while passing the 100-seed oracle. Two of the
|
||||
earlier sources were fixed rather than tolerated (`bdab558`): `Scroll` wrote
|
||||
a box it had been given back out as its own length in pixels, and `Span`
|
||||
placed each child a step from where the last ended rather than as the fixed
|
||||
parts before it plus one rounded share. See "Where the residual comes from"
|
||||
above for what closing the rest would cost.
|
||||
The frame/extent continuation removes `AGREE_STEPS`: warm and cold pixel
|
||||
regions must compare exactly. This is distinct from the equal-share test:
|
||||
when a row's grid-step count is not divisible by the number of children,
|
||||
individual share widths can differ while every rerun of that layout must
|
||||
still agree exactly. The PR #18 baseline still allows two position steps;
|
||||
its earlier failure at one step (`resize-size`, seeds 384 and 162 at depth 5)
|
||||
is a useful regression target for the experimental recomposition.
|
||||
|
||||
## Retained-layout invariants
|
||||
|
||||
|
||||
Reference in new issue
Block a user