Record the request arena, which replaces the second expression shape
This commit is contained in:
1 parent
5f01dc65c8
commit
a7da12a8ff
2 files changed
+82
-4
No files matched your search
+21
-4
@@ -8,9 +8,8 @@ found is in `docs/LAYOUT_LOG.md`.
|
|||||||
|
|
||||||
Bryan clarified that the built-in attribute should replace the wrapper.
|
Bryan clarified that the built-in attribute should replace the wrapper.
|
||||||
Work is in `/home/bob/repos/iris-deferred`, on `layout/one-ask`, at
|
Work is in `/home/bob/repos/iris-deferred`, on `layout/one-ask`, at
|
||||||
`ea1f836` (pushed), which is the eleventh sweep over `2ac0843`. Bounds now
|
`05e6ced` (pushed). Bounds now constrain the offer in `Placing::ask`;
|
||||||
constrain the offer in `Placing::ask`; declarations are retained as resolved
|
declarations are retained as resolved window lengths, so movement does not decide the bound again.
|
||||||
window lengths, so movement does not decide the bound again.
|
|
||||||
`.max_width`/`.max_height` now edit the same widget, like the minimum
|
`.max_width`/`.max_height` now edit the same widget, like the minimum
|
||||||
helpers, and `MaxSize` is removed. Preferred lengths and bounds are
|
helpers, and `MaxSize` is removed. Preferred lengths and bounds are
|
||||||
independent, so either order of `.width` and `.max_width` works. The app pin
|
independent, so either order of `.width` and `.max_width` works. The app pin
|
||||||
@@ -38,6 +37,21 @@ widget; all three allocation fixtures remain allocation-free after warm-up.
|
|||||||
`docs/LAYOUT.md` records the contract and measurements. Artifacts are in
|
`docs/LAYOUT.md` records the contract and measurements. Artifacts are in
|
||||||
`/tmp/attribute-bounds/`.
|
`/tmp/attribute-bounds/`.
|
||||||
|
|
||||||
|
## A request is held in the arena its nodes are allocated in
|
||||||
|
|
||||||
|
`05e6ced`. `SizeRequest` was a second expression shape beside the one
|
||||||
|
`RequestArena` already had -- the same three operators, the same constant fold
|
||||||
|
written twice, and an `import` that walked a pointer tree rebuilding it as
|
||||||
|
arena nodes. Bryan settled it on 2026-09-20: one node type, an arena, and no
|
||||||
|
refcount, since nothing shares a request and nothing outside widget code holds
|
||||||
|
one. A rule's expression now holds a small arena of the pass's own node type,
|
||||||
|
and `import` grafts those nodes across. A plain length stays inline, so
|
||||||
|
`size_of::<SizeRule>()` is 40 either way. `bounds_cost` `MODE=cap` is -1.34%
|
||||||
|
and `revision_cost` resize -0.79% in release instruction medians.
|
||||||
|
`docs/LAYOUT_LOG.md` has the full entry. Verified with all three seed scans,
|
||||||
|
the three deferred corpora, 206 and 210 tests, and the cold dump byte-identical
|
||||||
|
to `2ac0843` across all 34,986 boxes.
|
||||||
|
|
||||||
## A quality sweep of the bounds work is submitted on PR #19
|
## A quality sweep of the bounds work is submitted on PR #19
|
||||||
|
|
||||||
The eleventh sweep landed at `ea1f836`. It is the first review of `2ac0843`
|
The eleventh sweep landed at `ea1f836`. It is the first review of `2ac0843`
|
||||||
@@ -166,6 +180,9 @@ comparison work above, its review rounds past `cadfba0` are described in
|
|||||||
- **The deferred request system's own sweep**, `4cb6f68` -- described at the
|
- **The deferred request system's own sweep**, `4cb6f68` -- described at the
|
||||||
top of this file and in full in `docs/LAYOUT_LOG.md`.
|
top of this file and in full in `docs/LAYOUT_LOG.md`.
|
||||||
- **The bounds work's own sweep**, `ea1f836` -- the same, over `2ac0843`.
|
- **The bounds work's own sweep**, `ea1f836` -- the same, over `2ac0843`.
|
||||||
|
- **One node type for a request**, `05e6ced` -- the expression a rule holds
|
||||||
|
and the expression the pass allocates were two shapes of one thing, with
|
||||||
|
the fold written twice and an `Arc` where nothing shares.
|
||||||
|
|
||||||
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
|
||||||
@@ -221,7 +238,7 @@ the name it is reachable by.
|
|||||||
**Always**, because they cost nothing: format, workspace clippy under
|
**Always**, because they cost nothing: format, workspace clippy under
|
||||||
`-D warnings` with and without `layout-diagnostics`, the workspace tests, and
|
`-D warnings` with and without `layout-diagnostics`, the workspace tests, and
|
||||||
the **cold dump**. `layout_dump` over 400 depth-5 trees is **34,986** boxes
|
the **cold dump**. `layout_dump` over 400 depth-5 trees is **34,986** boxes
|
||||||
since `76aaf06` grew bounds in the trees, and is unchanged through `ea1f836`.
|
since `76aaf06` grew bounds in the trees, and is unchanged through `05e6ced`.
|
||||||
It was 34,571 from `2dba90b`, which grew the images, and 34,488 before those; the fourth through eighth sweeps all
|
It was 34,571 from `2dba90b`, which grew the images, and 34,488 before those; the fourth through eighth sweeps all
|
||||||
repeated 34,492, which is a `wc -l` of the whole run rather than of its box
|
repeated 34,492, which is a `wc -l` of the whole run rather than of its box
|
||||||
lines, so count the lines that are a box (`grep -cE '^[0-9]+ [0-9]+ '`). It is the only thing that catches two
|
lines, so count the lines that are a box (`grep -cE '^[0-9]+ [0-9]+ '`). It is the only thing that catches two
|
||||||
|
|||||||
@@ -6,6 +6,67 @@ nothing here is rediscovered. Each entry says who found it and when.
|
|||||||
it (settled design, the measurement method) belongs in `docs/LAYOUT.md`, and
|
it (settled design, the measurement method) belongs in `docs/LAYOUT.md`, and
|
||||||
the current plan is in `docs/HANDOFF.md`.
|
the current plan is in `docs/HANDOFF.md`.
|
||||||
|
|
||||||
|
## One node type for a request, and no refcount (2026-09-20)
|
||||||
|
|
||||||
|
`05e6ced`. `SizeRequest` was a second expression shape beside the one the
|
||||||
|
layout pass already had, and the `Arc` in it was how that showed. Bryan asked
|
||||||
|
the questions in this order: it is not exposed outside widget code, so it must
|
||||||
|
not be an `Arc`; why is it not a `Box`; where are the clones and can they be
|
||||||
|
references; is the tree duplicating one that exists; and ideally an arena,
|
||||||
|
because it is a single type.
|
||||||
|
|
||||||
|
**What was duplicated.** `SizeRequest` held `Sum`/`Min`/`Max` over
|
||||||
|
`Arc<(Self, Self)>`. `RequestArena` held the same three operators as
|
||||||
|
`Op` plus `Node { op, a, b }` in a `Vec`, reached through
|
||||||
|
`RequestedLen::Deferred { index, epoch, leftover }`. The constant fold was
|
||||||
|
written twice -- `SizeRequest::min`/`max`/`Add` and `RequestArena::combine`
|
||||||
|
both summed two linears, both resolved a comparison through
|
||||||
|
`independent_order`, and both collapsed equal operands -- and
|
||||||
|
`RequestArena::import` existed only to walk the first and rebuild it as the
|
||||||
|
second, recursively, at every ask.
|
||||||
|
|
||||||
|
**What it is now.** One `Node`, one `Op`, one fold in `Nodes::combine`, and
|
||||||
|
two kinds of owner: a rule's expression holds a small arena for as long as the
|
||||||
|
rule lasts, and `RequestArena` holds the pass's. `import` is
|
||||||
|
`Nodes::graft`, which copies nodes between two arenas with each length passed
|
||||||
|
through a `resolve` closure -- `within_len(base)` when importing, the identity
|
||||||
|
when the builder joins two expressions. A node's operand is an `Operand`, a
|
||||||
|
number within its own arena; `RequestedLen` is that plus the epoch saying
|
||||||
|
which pass numbered it, and is the only form that leaves an arena. The epoch
|
||||||
|
is therefore checked once where a handle comes back in (`RequestArena::operand`)
|
||||||
|
rather than at every level of the walk it starts, which also catches a stale
|
||||||
|
handle at `combine` rather than waiting for `segment`.
|
||||||
|
|
||||||
|
**No refcount replaces the `Arc`.** `SizeRequest::Linear(LayoutLen)` stays
|
||||||
|
inline and only `Expr(Box<Expr>)` allocates, so `size_of::<SizeRule>()` is 40
|
||||||
|
before and after -- the arena costs a widget nothing, because nearly every
|
||||||
|
rule holds a plain length. The only clones of a request in the framework were
|
||||||
|
`SizeRule::at_least` and `at_most`, and both read a rule out of a slot, moved
|
||||||
|
one end of its bound, and wrote it back into the same slot;
|
||||||
|
`Widgets::edit_bound` does that where it sits, and the two are gone. Every
|
||||||
|
read was already a reference (`size_rules` borrows, `deferred` returns
|
||||||
|
`Option<&SizeRequest>`, `import` takes `&SizeRequest`), and `WidgetData` is
|
||||||
|
not `Clone`. What is left is `src/random.rs`'s shrinker, where a deep copy of
|
||||||
|
a two-node expression at shrink time is nothing.
|
||||||
|
|
||||||
|
`SizeRequest` grew a `Display`, because the shrinker prints a rule and a
|
||||||
|
derived `Debug` of an arena is not something a tree can be rebuilt from. An
|
||||||
|
expression reads `min(30 px;1 leftover;, 2 leftover;)<0.5 rel;`.
|
||||||
|
|
||||||
|
**Measured**, medians of three release runs under `perf stat -e
|
||||||
|
instructions:u`, each set within 0.005% of its median: `bounds_cost`
|
||||||
|
`MODE=cap FRAMES=2000` is 5.665B against 5.743B (**-1.34%**), and
|
||||||
|
`revision_cost` resize `ROWS=40 FRAMES=500` is 4.855B against 4.893B
|
||||||
|
(**-0.79%**). Small, but consistent and well past the noise floor here.
|
||||||
|
|
||||||
|
Verified: format, workspace clippy under `-D warnings` with and without
|
||||||
|
`layout-diagnostics`, 206 ordinary and 210 diagnostic tests, the cold dump
|
||||||
|
byte-identical to `2ac0843` across all **34,986** boxes, all three seed scans
|
||||||
|
(400 at depth 5 in 64.24s, 1,000 at depth 6 in 160.35s, 2,000 at depth 4 in
|
||||||
|
298.82s), and 400 depth-5 trees in each of the three deferred-request corpora
|
||||||
|
in 205.42s. The scans were run because this replaces the allocator's data
|
||||||
|
structure, which is the one thing they exist to check.
|
||||||
|
|
||||||
## Eleventh sweep: the built-in bounds work (2026-09-20)
|
## Eleventh sweep: the built-in bounds work (2026-09-20)
|
||||||
|
|
||||||
Over `2ac0843`, which no earlier round reviewed -- `SizeRule` from an enum to
|
Over `2ac0843`, which no earlier round reviewed -- `SizeRule` from an enum to
|
||||||
|
|||||||
Reference in new issue
Block a user