Skip to content

Arena / SoA value store for the interpreted engine — perf follow-on, deferred on measured evidence #729

Description

@0-jake-0

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
Ceilingforward_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.
Floorforward_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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    coreCore Rust library functionalityenhancementNew feature or requestperformancePerformance improvementspriority: lowLow prioritysize: largeLarge effort (> 3 days)

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions