Record the fourteenth sweep, over allocation and the cost per child
The sweep is Iris `97fca76`. Its two largest findings are both costs per thing rather than per frame: a container's draw searched a list once per child and so cost the square of its children, and a mask's rectangle was resolved once per fragment rather than once per instance. Both now have a rig that can see them -- `children_cost.rs` is the only one here that varies width, and `chain_cost.rs` has a masked fixture beside its two-pixel quads. The sweep also settles the `Fixed::div`-versus-`ratio` item this file listed, by deleting the operation nothing performed, and adds to the pre-gate review's waiting list the `Arc<AtomicU32>` every `StrongWidget` allocates for a count it can never raise.
This commit is contained in:
1 parent
ea66fc3f71
commit
d24ff83d6b
2 files changed
+214
-2
No files matched your search
+59
-2
@@ -4,6 +4,55 @@ Where the work in flight stands. The settled layout design, the vocabulary
|
||||
and the measurement method are in `docs/LAYOUT.md`; what the review of #19
|
||||
found is in `docs/LAYOUT_LOG.md`.
|
||||
|
||||
## A sweep for allocation, and the cost per child, is on #19
|
||||
|
||||
The fourteenth sweep landed at `97fca76`. It read the whole branch again,
|
||||
aimed first at what allocates and then at whatever the reading turned up.
|
||||
Eight findings, the largest two both about cost per thing rather than per
|
||||
frame:
|
||||
|
||||
- **A container's draw was quadratic in its children.** Five per-child steps
|
||||
each asked "have I done this one already?" by searching a list; at 1,600
|
||||
children 70% of the redraw was those searches. A draw now takes a `DrawId`
|
||||
and leaves it on every widget it asks about, which answers the question in
|
||||
one read -- one note per widget suffices because the handle a container holds
|
||||
a child by cannot be cloned. `tests/children_cost.rs` is new and is the only
|
||||
rig here that varies width: 3.680 ms to 0.811 ms at 1,600 children, and flat
|
||||
per child at every count. A transcript is exactly this shape.
|
||||
- **A mask's rectangle was resolved once per fragment**, a walk up to 64 links
|
||||
long, although it is the same rectangle for every fragment of an instance.
|
||||
Resolved in the vertex stage now, which takes `masks` and `move_offsets` out
|
||||
of the fragment stage entirely. GPU timestamps over one screenful of clipped
|
||||
rows: 838.4 us to 95.7 us at chain depth 64, 141.2 to 69.4 at depth 8, and
|
||||
unchanged at depth 1. `chain_cost.rs` could not see this -- its instances are
|
||||
two pixels wide so vertex work dominates -- and has a masked fixture now.
|
||||
|
||||
The other six: `TextBuffer::shape` copying its attrs before the check that
|
||||
would not need them, which was one allocation per named-family text per frame
|
||||
and 800 to 0 over a measured hundred frames; `cargo test --release` failing,
|
||||
because a `#[should_panic]` test asserts a `debug_assert` release does not
|
||||
compile; `Fixed::div` and `Div for Fixed`, reached only by their own test,
|
||||
whose deletion also settles the `div`-versus-`ratio` zero-divisor item this
|
||||
file used to list; `Moves::remove` re-uploading an array it cannot have
|
||||
changed; and two comments this branch's own commits falsified -- one saying
|
||||
`widget_trait!` takes no attributes after `76aaf06` taught it to, one saying
|
||||
`Scroll` clips when masking is a capability a caller opts into with `Masked`.
|
||||
|
||||
It also left five things, with the numbers. Text allocates about six times per
|
||||
re-broken paragraph per frame, and removing all of them is **0.07%** of
|
||||
instructions (3.7107B to 3.7081B over 500 sweeping resize frames of 40
|
||||
paragraphs), so the count is recorded rather than the machinery built --
|
||||
allocation count and cost are not the same quantity, and this is where they
|
||||
part. `StrongWidget` carries an `Arc<AtomicU32>` it can never use, since it has
|
||||
no `Clone`; that and seven dead items older than #19 are listed under the
|
||||
pre-gate review below rather than fixed here.
|
||||
|
||||
`docs/LAYOUT_LOG.md` has all of it. Verified: format, clippy both ways, 190
|
||||
ordinary, 193 diagnostic and 189 release tests, the cold dump byte-identical to
|
||||
`cbccfb6` across all 34,986 boxes, all three seed scans, the three deferred
|
||||
corpora, and `mask_clip.rs` reading the clipped pixels back off the GPU to the
|
||||
same 6,000 in the same bounds before and after the shader change.
|
||||
|
||||
## Built-in bounds replace `MaxSize` on PR #19
|
||||
|
||||
Bryan clarified that the built-in attribute should replace the wrapper.
|
||||
@@ -238,6 +287,9 @@ comparison work above, its review rounds past `cadfba0` are described in
|
||||
- **A full sweep of the branch**, `cbccfb6` -- a length of zero that printed
|
||||
as nothing, a ceiling that stepped off the top of the grid, and a harness
|
||||
setter that dropped the bound beside the length it set.
|
||||
- **A sweep for allocation and the cost per child**, `97fca76` -- a
|
||||
container's draw quadratic in its children, and a mask's rectangle resolved
|
||||
once per fragment. Described at the top of this file.
|
||||
|
||||
The settled design of the vocabulary rounds is in `docs/LAYOUT.md` under
|
||||
"Three names, and the one argument that says them". Bryan settled the API
|
||||
@@ -349,6 +401,13 @@ a compile error, which reads exactly like a fuzzer failure.
|
||||
grammars of which `core/src/util/vec2.rs` uses two, one line apart.
|
||||
`Align` now has `Index<Axis>`, so the `if let Some` each
|
||||
`partial_align` writes twice collapses when that sweep reaches them.
|
||||
The fourteenth sweep adds more: `StrongWidget` allocates an
|
||||
`Arc<AtomicU32>` refcount it can never use, because it deliberately has no
|
||||
`Clone`, so every widget pays a heap allocation and two atomic
|
||||
read-modify-writes for a count that stays at zero, and `StrongWidget::refs`
|
||||
has no caller; and `Size::to_uivec2`, `Size::rel`, `Size::leftover`,
|
||||
`Len::to_uivec2`, `Vec2::with_x`, `Vec2::with_y`, `Vec2::ceil` and
|
||||
`Layers::iter_orderless_mut` are all dead.
|
||||
3. **Integrate the app's Iris capabilities before changing its pin.**
|
||||
`32f6ad8` has 45 commits not reachable from the review branch; shared UI
|
||||
ownership, richer masks, Android support, and app-side performance work
|
||||
@@ -380,8 +439,6 @@ glyphs do not follow a shortened entry.
|
||||
`rel(1.0)` and shares `Painter::longer_than` with the span. Done in
|
||||
`b295c8b`, and in `0d03267` for the root as well, which used to read it the
|
||||
old way.
|
||||
- `Fixed::div` by zero answers `MIN`/`MAX` while `ratio` answers `ZERO`; both
|
||||
are caller bugs under `debug_assert`, but the fallbacks differ.
|
||||
- `docs/LAYOUT.md` §4, §5 and the density section name `Painter::place`,
|
||||
`Painter::region()`, `SetSize`, `desired_width`, `apply_rest`, `Len::dp`,
|
||||
`Aligned`, which no longer exist; `MaxSize` now exists with the bounds API.
|
||||
|
||||
Reference in new issue
Block a user