Re-measure #18 against the code it replaces, and retire the tabs divergence

The tabs difference does not reproduce at f61e893 against upstream/main
built in its own worktree, so nothing is waiting on a decision. Records
the instruction counts, frame times and memory taken today rather than
mid-branch, and what a one-pixel line and a one-pixel gap do under the
chain, which is the question the pixel difference was really about.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
iris-aiandClaude Opus 5 committed 2026-09-15 02:56:11 -04:00
1 parent 155b7650a9
commit 89d20c31dc
1 file changed
+44 -12
+44 -12
View File
@@ -26,18 +26,14 @@ reference renders and the resize render are byte-identical across all of
it, and the hundred-seed sweep passes. `/home/bob/repos/ai-app-2` is on
`rustify`, worktree clean.
**The one thing waiting on the owner.** `tabs` at 1920x1200 is no longer
byte-identical to `upstream/main`: 1,283 pixels of 2.3M (0.06%), two
one-pixel-wide panel edges shifted by a pixel, at x=1056 and x=1337. `view`,
`minimal` and `text` are identical. Composing a position through the chain in
the shader associates the arithmetic differently from collapsing it on the CPU,
so a value that used to land exactly on an integer falls the other side of the
shader's `floor`. The CPU and the GPU still agree with each other -- both walk
the chain bottom-up -- so hit testing matches what is drawn; what changed is
only the comparison against the old code. Matching it exactly means composing
root-down in the shader, which needs the chain collected into an array first.
Byte-identical against `upstream/main` has been the bar for every slice, so
this is hers to accept or to spend a commit on.
**The `tabs` divergence does not reproduce, so nothing waits on the owner.**
Re-measured 2026-09-15 at `f61e893` against `upstream/main` built in its own
worktree: `tabs` at 1920x1200 is byte-identical, and so are a cold 900x1200 and
a resize from 1920x1200 down to it. Both sides render the same bytes twice, so
it is not a flaky shot. The earlier reading of 1,283 differing pixels at x=1056
and x=1337 is withdrawn; it was taken before `02ff8c7` and `f61e893`, and a
target directory shared between the two checkouts is the trap the render
section already warns about. Byte-identical against `upstream/main` is met.
Check for a review before starting anything, and read the newest `submitted_at`
rather than the first result:
@@ -102,6 +98,21 @@ Invariants, not history. Everything in `core/src/ui` rests on them.
Marking descendants for redraw instead does not terminate: the mark escalates
to that descendant's size reader, which re-places the child, which marks it
again. Asking first and giving up the whole reuse adds no marks and stops.
- **A fixed pixel length keeps its pixel width through any chain.** Both edges
of such a part share their box's `rel`, and `within` is a function of that
`rel` alone, so the shader's `floor(rel * dim)` is the same for both edges
while the `px` parts still differ by exactly one. A hairline or a one-pixel
gap can therefore move by a pixel when a position falls the other side of the
`floor`; it cannot be widened or deleted by one. Only a length expressed as a
fraction can round away, and that was as true before the chain. Measured
2026-09-15 with `examples/thin.rs` (untracked in the #18 worktree): sixteen
one-pixel lines and sixteen one-pixel gaps under four levels of span, padding
and `rest(3)/rest(7)/rest(5)`, rendered at six output sizes on
`upstream/main` and at `f61e893`. Every run is exactly one pixel on both, and
a line sits within one pixel of where the other revision put it. At 640x481
the fixture is over-constrained -- the fixed pixels exceed the box -- and the
same three gaps vanish on both revisions, which is the span overflowing
rather than anything rounding.
- **The walk stops where a length did not change.** A part of a box with no
relative extent on an axis is a fixed length held as offsets from that box's
start, and composing anything into it leaves no relative extent either -- so a
@@ -374,6 +385,23 @@ Memory on the same rig at 2,000 rows: 108.6 MB on #18's head, 111.6 MB with
both, and **132.0 MB before #16**, which grows 23 MB over the resizes where
neither of the others grows at all.
**Re-measured at `f61e893`, which is the number to quote.** The same rig, the
same two worktrees each with its own target directory, 500 resize frames at 40
rows, taken with `perf stat -e instructions:u` on the test binary:
| | before #16 (`43ce8c7`) | #18 head (`f61e893`) |
| --- | --- | --- |
| instructions/frame, alternating | 56.1M | 15.3M |
| instructions/frame, never repeating | 56.1M | 15.5M |
| median frame | 5.32 ms | 1.29 ms |
| worst frame | 8.06 ms | 1.81 ms |
| RSS after 40 resizes, 2,000 rows | 132.3 MB | 111.1 MB |
So it is 3.6x fewer instructions than the code it replaces, on top of being the
revision that asks in the right box: in the same 900-wide output the old code
lays the second paragraph out to x=929 and the third to x=910, both past the
edge, where this one keeps them at 877 and 889.
Widget draws do not move at all -- 449 either way -- so none of this touches a
retained-layout rule. That matters for more than purity: **text is the load
that makes a redundant draw expensive, and so the thing that shows when the
@@ -994,6 +1022,10 @@ holds a merged branch; they are readable references, not places to build.
"before" side of any measurement of the last two commits; `iris-size-old` is
`43ce8c7` with the old patched counters, and is how the pre-#16 column above
was measured. Copy `tests/revision_cost.rs` into either to compare.
`iris-old-cmp` (`43ce8c7`) and `iris-main-cmp` (`upstream/main`) are unpatched
worktrees with target directories of their own, for the instruction counts and
the reference renders above; `43ce8c7` calls it `Len::abs` where this branch
says `Len::px`, which is the only edit a copied fixture needs.
## Cautions