Surfacing a deferral that currently lives only in docs/port-plan.md §"Arena / SoA value store". Deliberately deferred, not dropped — filed so the trigger condition is visible in the tracker.
What
Move the per-slot Rc<RefCell<T>>s to a contiguous arena / structure-of-arrays store. A pure memory/throughput optimisation, semantics unchanged, which also enables zero-copy passthrough: a node that provably forwards its input aliases the upstream slot handle instead of cloning.
Why it is deferred
The interpreted engine is already at parity with legacy (the dirty-list did that), and nothing correctness-related depends on this. More importantly, the measured evidence says the payoff is workload-shaped:
bench (benches/store_baseline.rs) |
result |
Ceiling — forward_clone, 8 KiB Vec through 16 filter hops |
owned-Vec run is ~7.4× the Rc<Vec> run (≈20.8 ms vs ≈2.79 ms). Slot-aliasing has real teeth here. |
Floor — forward_scalar, same shape with an f64 payload |
≈1.84 ms — faster than the Rc<Vec> path, because a scalar clone is a register copy. Aliasing recovers nothing; only SoA cache locality is left, and this bench does not isolate it. |
Typical wingfoil workloads (scalars, small structs, statistics) sit near the floor. So: wait for a real big-payload-forwarding graph to appear. Regenerate the numbers before deciding — the ratios are machine-dependent, but the shape is the point.
The rework trap is already closed
The original risk was that every Builder registration closure captured the concrete slot type, so a naive swap would touch the whole catalog + adapters twice. Resolved — the slot API boundary is frozen by type. SlotRef<T> (interp.rs) is the sole access boundary: slot() / new_slot() return it, and every registration closure goes through SlotRef::borrow / borrow_mut, never the concrete cell. Audited: the macro crate never names the slot type (compiled uses locals), and Stream::__slot for nested islands returns SlotRef<T> too.
So the arena is an internal swap of SlotRef's innards with zero capture sites touched — which is what makes "later" free.
Trigger
A measured need on a graph that forwards large payloads by clone.
Surfacing a deferral that currently lives only in
docs/port-plan.md§"Arena / SoA value store". Deliberately deferred, not dropped — filed so the trigger condition is visible in the tracker.What
Move the per-slot
Rc<RefCell<T>>s to a contiguous arena / structure-of-arrays store. A pure memory/throughput optimisation, semantics unchanged, which also enables zero-copy passthrough: a node that provably forwards its input aliases the upstream slot handle instead of cloning.Why it is deferred
The interpreted engine is already at parity with legacy (the dirty-list did that), and nothing correctness-related depends on this. More importantly, the measured evidence says the payoff is workload-shaped:
benches/store_baseline.rs)forward_clone, 8 KiBVecthrough 16filterhopsVecrun is ~7.4× theRc<Vec>run (≈20.8 ms vs ≈2.79 ms). Slot-aliasing has real teeth here.forward_scalar, same shape with anf64payloadRc<Vec>path, because a scalar clone is a register copy. Aliasing recovers nothing; only SoA cache locality is left, and this bench does not isolate it.Typical wingfoil workloads (scalars, small structs, statistics) sit near the floor. So: wait for a real big-payload-forwarding graph to appear. Regenerate the numbers before deciding — the ratios are machine-dependent, but the shape is the point.
The rework trap is already closed
The original risk was that every
Builderregistration closure captured the concrete slot type, so a naive swap would touch the whole catalog + adapters twice. Resolved — the slot API boundary is frozen by type.SlotRef<T>(interp.rs) is the sole access boundary:slot()/new_slot()return it, and every registration closure goes throughSlotRef::borrow/borrow_mut, never the concrete cell. Audited: the macro crate never names the slot type (compiled uses locals), andStream::__slotfornestedislands returnsSlotRef<T>too.So the arena is an internal swap of
SlotRef's innards with zero capture sites touched — which is what makes "later" free.Trigger
A measured need on a graph that forwards large payloads by clone.