Record frame-extent performance gains and alignment verification
This commit is contained in:
1 parent
8f1a5e0a46
commit
264dc4f0c2
2 files changed
+90
-42
No files matched your search
+86
-41
@@ -422,8 +422,9 @@ 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 first correction is `efb416b`; the exact-recomposition continuation is
|
||||
`2ed5503`, pushed to origin's `wip/region-and-placement`, in the isolated checkout
|
||||
The first correction is `efb416b`, exact recomposition is `2ed5503`, and the
|
||||
current performance/alignment continuation is **`7601aa2`**, 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
|
||||
@@ -436,7 +437,7 @@ report must not replace the reference against which that report was obtained.
|
||||
Text wraps at the available extent, not the whole fraction reference.
|
||||
|
||||
**The offer includes availability.** A span can keep the same reference frame
|
||||
while offering a text less room after an earlier sibling. `known_len` therefore
|
||||
while offering a text less room after an earlier sibling. `measure_len` therefore
|
||||
accepts the placement as well as the frame. The first measurement's
|
||||
`offer_placement` survives later placing evaluations, and local redraw asks
|
||||
that original question before restoring the assigned slot. Frame-length
|
||||
@@ -484,52 +485,96 @@ 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).
|
||||
|
||||
**Measure the offer without placing an intermediate answer.** `Painter::measure_len`
|
||||
replaces the hint/cache query and its duplicated drawing fallback. It still runs
|
||||
`Widget::draw` when needed, but leaves that drawing in the offer until the parent
|
||||
assigns the child's slot. Placing the child's own answer first was wasted work:
|
||||
the parent immediately replaced that placement. The regression counts three
|
||||
rather than four evaluations for a numeric-size leaf in a span, checks its actual
|
||||
primitive bounds, and repeats after resize. There is no second layout body on
|
||||
`Widget`. `Holds::ANY.through(...)` now returns `ANY` directly: an unrestricted
|
||||
range needs no inverse division, including for a negative fraction.
|
||||
|
||||
**A chosen slot does not cancel a child's alignment.** Bryan caught this in the
|
||||
`tabs` image: a fixed 100 px square under a flexible wrapper sat at the slot's
|
||||
near edge. `ask_box` now aligns a declared frame inside the chosen slot, just as
|
||||
it does inside an unassigned offer. A regression asserts the actual coordinates
|
||||
before and after resize. Warm/cold equality could not find this because both
|
||||
were wrong. The corrected 900 px image still has 88 px between blue and red and
|
||||
78 px between red and orange: the enclosing `.pad(10)` adds 10 px before the
|
||||
red slot. Red is centered in that slot, 5 px right of the visible black gap's
|
||||
center. Do not describe those two centers as the same thing or compensate with
|
||||
an arbitrary offset. The parked padding API change is still separate.
|
||||
|
||||
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.
|
||||
`layout-diagnostics`, workspace tests (100 suite tests and 21 core tests), and
|
||||
the fast generated cases. The corrected `tabs` resize from 1920x1200 to
|
||||
900x1200 matches a cold image with zero differing pixels. The release oracle
|
||||
passes 2000 seeds at depth 4 and 1000 at depth 6; the shrinker passes 400 at
|
||||
depth 5, and the debug oracle passes 120 at depth 4 with assertions enabled.
|
||||
Every scan runs all fifteen scenarios with exact equality. The measurement
|
||||
regression fails with four draws instead of three when the optimization is
|
||||
disabled.
|
||||
|
||||
**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. 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):
|
||||
**Still not ready to replace PR #18.** The prototype does substantially more
|
||||
nested layout work than `e44dea3`, even after removing intermediate placements
|
||||
(seed 1, depth 8):
|
||||
|
||||
| phase | widget draws before | prototype | primitive writes before | prototype |
|
||||
| phase | widget draws at e44dea3 | current | primitive writes at e44dea3 | current |
|
||||
| --- | ---: | ---: | ---: | ---: |
|
||||
| cold | 369 | 498 | 9635 | 9704 |
|
||||
| cold | 369 | 484 | 9635 | 9179 |
|
||||
| repaint | 1 | 1 | 1 | 1 |
|
||||
| many | 157 | 282 | 4721 | 6398 |
|
||||
| size | 16 | 254 | 106 | 5725 |
|
||||
| many | 157 | 274 | 4721 | 5873 |
|
||||
| size | 16 | 247 | 106 | 5200 |
|
||||
| scroll | 2 | 2 | 0 | 0 |
|
||||
| resize | 13 | 300 | 0 | 6255 |
|
||||
| resize | 13 | 292 | 0 | 5730 |
|
||||
|
||||
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.
|
||||
These are instrumented work counts, not speedups (50 frames per phase except
|
||||
cold, which is one; 578 generated widgets, 191 finally active). Against
|
||||
`2ed5503`, the changes remove 7 widget draws and 525 primitive writes per size
|
||||
frame, and 8 draws and 525 writes per resize frame.
|
||||
|
||||
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`
|
||||
body, not a finished performance replacement. Optimize the container protocol
|
||||
under the same correctness tests before adopting it. The parked `Inset`/`Outset`
|
||||
API changes are not included in this experiment.
|
||||
**Measure cycles as well as instructions** (Bryan, 2026-09-17). The following
|
||||
are whole-process medians from seven alternating before/after runs of direct,
|
||||
uninstrumented release test executables under `perf stat -e
|
||||
cycles:u,instructions:u`. The baseline is `39f7b08`: `2ed5503` with the same
|
||||
centering fix, so both sides draw the corrected layout. CPU-heavy scans were stopped
|
||||
during measurement. Counts include fixture setup; size, resize and many run
|
||||
5000 frames, repaint and scroll run 1,000,000. These are VM CPU measurements,
|
||||
not phone frame times.
|
||||
|
||||
| phase | cycles before → after (billions) | instructions before → after (billions) |
|
||||
| --- | ---: | ---: |
|
||||
| size | 12.8008 → 11.0344 (-13.8%) | 34.3660 → 29.9450 (-12.9%) |
|
||||
| resize | 14.9368 → 13.0376 (-12.7%) | 39.8487 → 35.0032 (-12.2%) |
|
||||
| many | 14.8875 → 12.9579 (-13.0%) | 39.6021 → 34.7499 (-12.3%) |
|
||||
| repaint | 2.7416 → 2.6626 (-2.9%) | 6.0266 → 6.0197 (-0.1%) |
|
||||
| scroll | 9.7848 → 8.4829 (-13.3%) | 21.7203 → 20.9527 (-3.5%) |
|
||||
|
||||
The size/resize/many cycle samples have nonoverlapping before/after ranges,
|
||||
with each range less than 1.3% of its median. Additional depth-6 fixtures,
|
||||
10,000 frames and seven alternating pairs each: seed 3 improves cycles by
|
||||
7.0% for size and 8.4% for resize; seed 13 improves resize by 9.2%, while its
|
||||
size samples overlap and establish no cycle improvement.
|
||||
|
||||
**The remaining gap has not been established as an unavoidable correctness
|
||||
cost.** A temporary failure trace of one frame on seed 1, depth 8 counted
|
||||
39/108 failed reuse attempts in size, 65/151 in resize, and 45/109 in many
|
||||
where only the raw placement snapshot differed: both numeric frame and extent
|
||||
ranges still held. Containers read that snapshot to construct child positions,
|
||||
so discarding the check would be wrong; a way to retain those child positions
|
||||
relative to the extent is the next protocol question. There is also necessary
|
||||
width-dependent work: the hot text at widget 199 visits 68 px and 89.53613 px
|
||||
and reports different heights (316.80078 and 228.80078). It is evaluated
|
||||
repeatedly at those widths, so that fact alone does not justify all the repeats.
|
||||
|
||||
Keeping measurement validity separate from final drawing validity and deferring
|
||||
to an already dirty parent were previously tried without improving draw counts.
|
||||
Measuring first in local redraw and then restoring its slot saved only one draw
|
||||
in `many` and added another request on simple repaints; that trial was removed.
|
||||
Retaining local coordinates still costs memory per primitive. Optimize under
|
||||
the exact oracle before adopting the prototype; the `Inset`/`Outset` changes
|
||||
remain parked.
|
||||
|
||||
## How layout is decided
|
||||
|
||||
|
||||
Reference in new issue
Block a user