Record what wrapping saved, and the rounding question left open

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
iris-aiandClaude Fable 5.1 committed 2026-09-16 14:23:22 -04:00
1 parent 9ed90505b3
commit 663a95f4a2
1 file changed
+35 -11
+35 -11
View File
@@ -8,7 +8,7 @@ log.
Canonical Iris `main` is **`ca2b4b2`** (#17, the headless rig). **#18 Canonical Iris `main` is **`ca2b4b2`** (#17, the headless rig). **#18
`split/18-position-chain`** is open in `/home/bob/repos/iris-pr18`; its local `split/18-position-chain`** is open in `/home/bob/repos/iris-pr18`; its local
head is **`394d514`**, seventy commits. Built-in alignment is complete there; head is **`4febabf`**, seventy-one commits. Built-in alignment is complete there;
see "Built-in alignment" below for the retained-layout details. No PR reviews see "Built-in alignment" below for the retained-layout details. No PR reviews
were present when checked on 2026-09-15. were present when checked on 2026-09-15.
@@ -91,6 +91,11 @@ pin those rules. Seeds 10 and 86 are now in the ordinary generated set.
## Verification at `394d514` ## Verification at `394d514`
`4febabf` on top of it -- `Fixed` wrapping rather than saturating -- passed
the workspace tests with all features (105), the release 100-seed oracle in
9.5 s, and rendered `random`, `tabs` and `text` byte-identical at 1920x1200
against `394d514`. The measurements are under "Performance".
- `cargo fmt --all --check` - `cargo fmt --all --check`
- `cargo build --workspace --all-features` - `cargo build --workspace --all-features`
- `cargo clippy --workspace --all-targets --all-features -- -D warnings` - `cargo clippy --workspace --all-targets --all-features -- -D warnings`
@@ -160,9 +165,14 @@ Measured on the fixed-shape fixture, seed 1, depth 8, 500 frames of `many`:
| --- | ---: | ---: | ---: | ---: | | --- | ---: | ---: | ---: | ---: |
| `5ed9e87`, before fixed point | 100 | 4,272 | 1,761M | ~699M | | `5ed9e87`, before fixed point | 100 | 4,272 | 1,761M | ~699M |
| `4cbb242` | 97 | 3,951 | 2,093M | ~819M | | `4cbb242` | 97 | 3,951 | 2,093M | ~819M |
| `4febabf`, wrapping | 97 | 3,951 | 1,918M | ~771M |
So the grid costs something like a fifth to a quarter, on a head that draws Normalised by primitive writes the grid is now about 1.18x the float head
slightly less. Normalised by primitive writes it is about 1.27x. on instructions and 1.19x on cycles; per drawn widget it is 1.12x. What is
left is the shape of an integer multiply with a rounding against a float
fused multiply-add, spread across `UiSpan::within` (4.7% of cycles),
`remap_subtree` and `Holds::through`; nothing in the profile above those
is the grid. Text line breaking is 10% and `InstanceList::push` 9%.
**Cycles are measurable on this machine and instructions alone are not **Cycles are measurable on this machine and instructions alone are not
enough.** Three runs of one binary varied 0.23%. It is *wall time* that enough.** Three runs of one binary varied 0.23%. It is *wall time* that
@@ -200,12 +210,22 @@ Tried and rejected, with numbers, so they are not tried again:
- Short-circuiting `apply_scalar` where the fraction is nought or one: +17%. - Short-circuiting `apply_scalar` where the fraction is nought or one: +17%.
(From the previous session.) (From the previous session.)
**The one lever left that is worth a decision:** `Fixed`'s `saturating_add` - `#[inline]` on `UiSpan::within`, whose prologue and epilogue were a sixth
and `saturating_sub`, measured at **8.1% of instructions and 2.7% of of its own cycles: -0.2% instructions, **+1.5% cycles**.
cycles**. Wrapping instead is one instruction where saturating is five. That
trades away "a clamped coordinate keeps the ordering a wrapped one inverts", **`4febabf` makes `Fixed` wrap rather than saturate** (Bryan, 2026-09-16: a
which is a posture rather than a micro-optimisation, so it needs Bryan. coordinate past the range is not going to draw reasonably anyway, so wrap
Everything else is spread thin. and break clearly): -8.6% instructions, -6.6% cycles, more on cycles than
the 2.7% the instruction share predicted. `from_f32` still clamps and
`Holds` keeps its saturating `narrow`, since a range of box lengths past
`i32` really is unbounded.
**One posture question is still open, with its number.** `shift_round`
rounds halves away from zero so a value and its negation round to the same
distance, which is a sign branch on every multiply. Rounding halves up
instead measured **-1.6% instructions, -2% cycles** (1,888M, ~757M), and
would let a flipped span land a step from its mirror image at exact halves.
Not applied; Bryan's call.
Earlier, against #18's own history: the retained rewrite took `many` from Earlier, against #18's own history: the retained rewrite took `many` from
25.17M instructions a frame at `691e3eb` to 6.14M at `29c7881`, and `resize` 25.17M instructions a frame at `691e3eb` to 6.14M at `29c7881`, and `resize`
@@ -417,8 +437,12 @@ pixels and `Holds`. Decided with Bryan on 2026-09-15.
- A weight is not a fraction: a list divides its room by the total of its - A weight is not a fraction: a list divides its room by the total of its
weights, so `Weight` trades precision for the range to hold a whole list, weights, so `Weight` trades precision for the range to hold a whole list,
and `Rel::ratio` turns two weights into a share on the finer grid. and `Rel::ratio` turns two weights into a share on the finer grid.
- **Arithmetic saturates rather than wrapping**, because a clamped coordinate - **Arithmetic wraps, as of `4febabf`.** It saturated first, so that a
keeps the ordering a wrapped one inverts. clamped coordinate kept the ordering a wrapped one inverts, and that cost
a twelfth of layout's instructions to keep order two million pixels out
where nothing draws. `MIN` and `MAX` still stand in for an unbounded end,
which is safe only because every use compares against them and none adds
to them; `from_f32` is the one operation that clamps.
- `Px` was `1/64` first. The residue of a length reached two ways is one - `Px` was `1/64` first. The residue of a length reached two ways is one
rounding, so it scales with the step: at `1/64` that was 0.016 px, enough rounding, so it scales with the step: at `1/64` that was 0.016 px, enough
to move a box, and at `1/1024` it is a thousandth of a pixel. Range is to move a box, and at `1/1024` it is a thousandth of a pixel. Range is