Skip to content

spread() creates three reactive nodes per element #3388

Description

@ryansolid

Version: 2.0.0-rc.8 (@solidjs/web), packages/web/src/client.ts ~809 (// TODO: make this better)

spread(node, props, skipChildren) currently sets up (a) a render effect assigning props, (b) a separate one for children when not skipped, and (c) the props-collection memo, on top of a prevProps object per element. Every element rendered through Dynamic, dynamic(), or any component that forwards {...props} to an intrinsic pays this; the compiler only avoids it for statically-known attributes.

Measured

ryansolid/yak-bench, Chromium 4× throttle, @yak/solid PR head on rc.8. btn-variant and compose-1 render the same <button> × 1000; the only difference is dynamic $props (so a memo + spread) versus a static class baked into the template:

hydrate mount SSR inst/s
compose-1 (static) 15.7 ms 9.3 ms 10.0M
btn-variant (spread) 30.4 ms 22.6 ms 2.7M

The styled(Component) cases (tabs, multifile-composition) that go createComponentomit{...rest} spread → element are the only ones still slower than React on hydrate (0.45×) and mount (0.63×). Full tables in the perf tracker, #3389.

Proposal

  • One render effect per element that owns the diff: iterate the (already collected) prop keys, compare against prevProps, assign changed ones; children handled inside the same effect via insert when present.
  • Static fast path when the accessor is a plain object without $PROXY (rc.8 4e730a9 already does the collection half of this): assign once, no effect at all unless a getter is present.
  • Keep prevProps off the element when there's nothing reactive to diff against.

Acceptance: a yak-runtime variant that forwards to spread lands within noise of yak's hand-rolled createElementRenderer on btn-variant and tabs in the harness; no change to the hydratable fixtures' output.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions