Record the refcount removal beside the sweep that raised it
This commit is contained in:
1 parent
d24ff83d6b
commit
6450615434
2 files changed
+45
-26
No files matched your search
+21
-17
@@ -6,10 +6,10 @@ found is in `docs/LAYOUT_LOG.md`.
|
|||||||
|
|
||||||
## A sweep for allocation, and the cost per child, is on #19
|
## A sweep for allocation, and the cost per child, is on #19
|
||||||
|
|
||||||
The fourteenth sweep landed at `97fca76`. It read the whole branch again,
|
The fourteenth sweep landed at `97fca76`, with the refcount removal below at
|
||||||
aimed first at what allocates and then at whatever the reading turned up.
|
`429a4f1`. It read the whole branch again, aimed first at what allocates and
|
||||||
Eight findings, the largest two both about cost per thing rather than per
|
then at whatever the reading turned up. Nine findings, the largest two both
|
||||||
frame:
|
about cost per thing rather than per frame:
|
||||||
|
|
||||||
- **A container's draw was quadratic in its children.** Five per-child steps
|
- **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
|
each asked "have I done this one already?" by searching a list; at 1,600
|
||||||
@@ -38,14 +38,21 @@ changed; and two comments this branch's own commits falsified -- one saying
|
|||||||
`widget_trait!` takes no attributes after `76aaf06` taught it to, 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`.
|
`Scroll` clips when masking is a capability a caller opts into with `Masked`.
|
||||||
|
|
||||||
|
The ninth is the one Bryan asked for on 2026-09-21, having first been left for
|
||||||
|
the pre-gate pass: `StrongWidget` allocated a `RefCounter(Arc<AtomicU32>)` it
|
||||||
|
could never use, since it deliberately has no `Clone`, so every widget paid a
|
||||||
|
heap allocation and two atomic read-modify-writes for a count that stayed at
|
||||||
|
zero. It is the id, the sender and the type now, and `Drop` sends;
|
||||||
|
`size_of::<StrongWidget>()` is 32 rather than 40. `RefCounter` stays for
|
||||||
|
`TextureHandle`, which does clone, trimmed to what that needs.
|
||||||
|
|
||||||
It also left five things, with the numbers. Text allocates about six times per
|
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
|
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
|
instructions (3.7107B to 3.7081B over 500 sweeping resize frames of 40
|
||||||
paragraphs), so the count is recorded rather than the machinery built --
|
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
|
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
|
part. Seven dead items older than #19 are listed under the pre-gate review
|
||||||
no `Clone`; that and seven dead items older than #19 are listed under the
|
below rather than fixed here.
|
||||||
pre-gate review below rather than fixed here.
|
|
||||||
|
|
||||||
`docs/LAYOUT_LOG.md` has all of it. Verified: format, clippy both ways, 190
|
`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
|
ordinary, 193 diagnostic and 189 release tests, the cold dump byte-identical to
|
||||||
@@ -287,9 +294,10 @@ comparison work above, its review rounds past `cadfba0` are described in
|
|||||||
- **A full sweep of the branch**, `cbccfb6` -- a length of zero that printed
|
- **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
|
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.
|
setter that dropped the bound beside the length it set.
|
||||||
- **A sweep for allocation and the cost per child**, `97fca76` -- a
|
- **A sweep for allocation and the cost per child**, `97fca76` and `429a4f1`
|
||||||
container's draw quadratic in its children, and a mask's rectangle resolved
|
-- a container's draw quadratic in its children, a mask's rectangle resolved
|
||||||
once per fragment. Described at the top of this file.
|
once per fragment, and the refcount a widget handle can never raise.
|
||||||
|
Described at the top of this file.
|
||||||
|
|
||||||
The settled design of the vocabulary rounds is in `docs/LAYOUT.md` under
|
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
|
"Three names, and the one argument that says them". Bryan settled the API
|
||||||
@@ -401,13 +409,9 @@ a compile error, which reads exactly like a fuzzer failure.
|
|||||||
grammars of which `core/src/util/vec2.rs` uses two, one line apart.
|
grammars of which `core/src/util/vec2.rs` uses two, one line apart.
|
||||||
`Align` now has `Index<Axis>`, so the `if let Some` each
|
`Align` now has `Index<Axis>`, so the `if let Some` each
|
||||||
`partial_align` writes twice collapses when that sweep reaches them.
|
`partial_align` writes twice collapses when that sweep reaches them.
|
||||||
The fourteenth sweep adds more: `StrongWidget` allocates an
|
The fourteenth sweep adds more, all dead: `Size::to_uivec2`, `Size::rel`,
|
||||||
`Arc<AtomicU32>` refcount it can never use, because it deliberately has no
|
`Size::leftover`, `Len::to_uivec2`, `Vec2::with_x`, `Vec2::with_y`,
|
||||||
`Clone`, so every widget pays a heap allocation and two atomic
|
`Vec2::ceil` and `Layers::iter_orderless_mut`.
|
||||||
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.**
|
3. **Integrate the app's Iris capabilities before changing its pin.**
|
||||||
`32f6ad8` has 45 commits not reachable from the review branch; shared UI
|
`32f6ad8` has 45 commits not reachable from the review branch; shared UI
|
||||||
ownership, richer masks, Android support, and app-side performance work
|
ownership, richer masks, Android support, and app-side performance work
|
||||||
|
|||||||
+24
-9
@@ -10,7 +10,7 @@ the current plan is in `docs/HANDOFF.md`.
|
|||||||
|
|
||||||
Over the whole branch again, aimed first at what allocates -- `Vec`s, `Arc`s,
|
Over the whole branch again, aimed first at what allocates -- `Vec`s, `Arc`s,
|
||||||
capacity dropped and re-grown -- and then at whatever else the reading turned
|
capacity dropped and re-grown -- and then at whatever else the reading turned
|
||||||
up. Eight findings.
|
up. Nine findings.
|
||||||
|
|
||||||
- **A container's draw was quadratic in its children.** Every per-child step
|
- **A container's draw was quadratic in its children.** Every per-child step
|
||||||
in one draw asked "have I done this one already?" by searching a list:
|
in one draw asked "have I done this one already?" by searching a list:
|
||||||
@@ -116,7 +116,24 @@ up. Eight findings.
|
|||||||
does not clip it, because masking is a capability a caller opts into by
|
does not clip it, because masking is a capability a caller opts into by
|
||||||
putting a `Masked` around it. The code is right; the reason was not.
|
putting a `Masked` around it. The code is right; the reason was not.
|
||||||
|
|
||||||
Five things the sweep **looked at and left**:
|
- **`StrongWidget` carried a `RefCounter(Arc<AtomicU32>)` it could never
|
||||||
|
use.** It deliberately has no `Clone`, so the count never rose above zero,
|
||||||
|
`RefCounter::drop` always answered true, and `StrongWidget::refs` had no
|
||||||
|
caller -- while every widget made paid a heap allocation and every one
|
||||||
|
created or dropped paid two atomic read-modify-writes. Removed: the handle is
|
||||||
|
the id, the sender and the type, and `Drop` sends. It is 32 bytes rather than
|
||||||
|
40, and 40 rather than 48 for a `dyn` one. Raised as something to leave for
|
||||||
|
the pre-gate pass, `handle.rs` being outside #19, and Bryan asked for it here
|
||||||
|
(2026-09-21): not being `Clone` is what makes one handle the only one, which
|
||||||
|
is the same fact the child note above rests on.
|
||||||
|
|
||||||
|
`RefCounter` stays for `TextureHandle`, which does clone -- several widgets
|
||||||
|
showing one picture share its slot -- and is down to what that needs:
|
||||||
|
`quiet_clone` and `refs` had no callers at all, and `new` was `Default` spelt
|
||||||
|
out, so the default is derived now and says in one line that zero means one
|
||||||
|
handle.
|
||||||
|
|
||||||
|
Four things the sweep **looked at and left**:
|
||||||
|
|
||||||
- **Text allocates about six times per re-broken paragraph per frame**, and it
|
- **Text allocates about six times per re-broken paragraph per frame**, and it
|
||||||
is not worth removing. One is the whole text copied into the placement store
|
is not worth removing. One is the whole text copied into the placement store
|
||||||
@@ -129,13 +146,6 @@ Five things the sweep **looked at and left**:
|
|||||||
is **0.07%**. The machinery is two pools and a changed `place` signature for
|
is **0.07%**. The machinery is two pools and a changed `place` signature for
|
||||||
that, so the count is recorded here instead. Allocation count is not the
|
that, so the count is recorded here instead. Allocation count is not the
|
||||||
same quantity as cost, and this is where the two part.
|
same quantity as cost, and this is where the two part.
|
||||||
- **`StrongWidget` carries a `RefCounter(Arc<AtomicU32>)` it can never use.**
|
|
||||||
`StrongWidget` deliberately has no `Clone`, so the count never rises above
|
|
||||||
zero and `RefCounter::drop` always answers true -- but every widget still
|
|
||||||
allocates an `Arc`, and creating and dropping one is two atomic
|
|
||||||
read-modify-writes. `StrongWidget::refs` has no caller. `handle.rs` is
|
|
||||||
untouched by #19, so this belongs to the review of the code written before
|
|
||||||
the gate; recorded there.
|
|
||||||
- **More for that same pass, all dead and all older than #19**:
|
- **More for that same pass, all dead and all older than #19**:
|
||||||
`Size::to_uivec2`, `Size::rel`, `Size::leftover`, `Len::to_uivec2`,
|
`Size::to_uivec2`, `Size::rel`, `Size::leftover`, `Len::to_uivec2`,
|
||||||
`Vec2::with_x`, `Vec2::with_y`, `Vec2::ceil`, `Layers::iter_orderless_mut`.
|
`Vec2::with_x`, `Vec2::with_y`, `Vec2::ceil`, `Layers::iter_orderless_mut`.
|
||||||
@@ -151,6 +161,11 @@ Five things the sweep **looked at and left**:
|
|||||||
the duplication is bounded by what the caller wrote rather than by anything
|
the duplication is bounded by what the caller wrote rather than by anything
|
||||||
the arena does on its own.
|
the arena does on its own.
|
||||||
|
|
||||||
|
One more thing **looked at and left** in passing: `RefCounter` decrements with
|
||||||
|
`Ordering::Release` and has no acquire on the last drop, which is the shape an
|
||||||
|
`Arc` gets wrong when handles cross threads. Left because nothing here is
|
||||||
|
threaded and the orderings are not this sweep's to guess at.
|
||||||
|
|
||||||
Verified at the sweep's tip: format, workspace clippy under `-D warnings` with
|
Verified at the sweep's tip: format, workspace clippy under `-D warnings` with
|
||||||
and without `layout-diagnostics`, **190** ordinary, **193** diagnostic and
|
and without `layout-diagnostics`, **190** ordinary, **193** diagnostic and
|
||||||
**189** release tests (188 and 191 before, with release failing), and the cold
|
**189** release tests (188 and 191 before, with release failing), and the cold
|
||||||
|
|||||||
Reference in new issue
Block a user