Skip to content

perf: cheaper reactive ui mounting - #719

Draft
makspll wants to merge 13 commits into
agent/reactive-ui-signalsfrom
agent/reactive-ui-mount-perf
Draft

makspll wants to merge 13 commits into
agent/reactive-ui-signalsfrom
agent/reactive-ui-mount-perf

Conversation

@makspll

@makspll makspll commented Nov 13, 2026

Copy link
Copy Markdown
Owner

Mount optimisations for the reactive UI, on top of #714:

  • elements cross to scripts as integer handles into a per-flush arena (no allocation for scripts, reflection or access claims when building and reading elements; stale handles error clearly)
  • elements are spawned with their static components, handlers and bound components in one bundle
bench (closures / paths) #714 this PR
inventory mount or unmount 200 2.48 / 2.67 ms 2.19 / 2.48 ms
inventory search 2.30 / 2.39 ms 2.07 / 2.26 ms

Most of what is left is script side: props table conversion, component renders and the first run of bindings.

Adds AppScriptCallbackRunners::run_in_context, backed by a context runner
each scripting plugin registers. The locking part of handle is extracted
into run_in_script_context so both share the same re-entry handling.
Adds bevy_mod_scripting_reactive_ui: script described bevy_ui trees where
components run once, bound properties and dynamic regions re-run when the
signals they read change, and reloads keep component state.
- keep the interaction query between flushes, poll watched components once
  per flush (again only after handlers or effects ran), skip idle flushes
- computeds only wake their readers when their value changed (push-pull)
- ui.selector: selector:is(key) only re-runs the readers of the old and
  new key, so selecting in a list re-runs two items instead of all
ui.path, ui.format, ui.percent, ui.lt, ui.mul, ui.select and ui.is build
UiValues: properties made of them know what they read up front and update
without running script code or entering the script's context.
Elements cross to scripts as plain integers, so building and reading them
needs no allocation for scripts, reflection or access claims. Handles are
checked against the flush that built them.
Static properties, handlers and the components bound properties write are
set up before spawning, so mounting an element places it in its archetype
once instead of moving it per inserted component.
@makspll
makspll added this pull request to stack #718 November 13, 2026 01:13
@semanticdiff-com

semanticdiff-com Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

Review changes with  SemanticDiff

Changed Files
File Status
  crates/bevy_mod_scripting_reactive_ui/src/lib.rs  80% smaller
  crates/bevy_mod_scripting_reactive_ui/src/runtime.rs  23% smaller
  crates/bevy_mod_scripting_reactive_ui/src/element.rs  21% smaller

component, element, render, show, when, selected, background_color, flex_direction.
select and is are keywords in Rune.
…-perf

# Conflicts:
#	crates/bevy_mod_scripting_reactive_ui/src/lib.rs
…-perf

# Conflicts:
#	crates/bevy_mod_scripting_reactive_ui/src/element.rs
#	crates/bevy_mod_scripting_reactive_ui/src/lib.rs
#	crates/bevy_mod_scripting_reactive_ui/src/runtime.rs

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant