Skip to content

feat: reactive ui lists which only build new items - #723

Open
makspll wants to merge 5 commits into
agent/reactive-ui-mount-perffrom
agent/reactive-ui-each
Open

makspll wants to merge 5 commits into
agent/reactive-ui-mount-perffrom
agent/reactive-ui-each

Conversation

@makspll

@makspll makspll commented Nov 13, 2026

Copy link
Copy Markdown
Owner

ui.each(items, function(item) .. end): a region with one child per item of the list held by a signal. Children are kept by item (the item is the key, as key is for ui.el), so the function only runs for items which were not in the list before. A ui.dynamic list re-runs the whole loop on every change: one ui.el call and props conversion per row, kept or not.

ui.each(visible, function(name)
    return ui.el(Slot, { name = name, entity = entities[name], selected = is_selected, on_select = select })
end)
  • What the function reads is not tracked: it builds a child once. When the parent renders again (i.e. a reload) the kept children are built again and patched, as ui.dynamic does.
  • The inventory test and benches use it for their list, ui.dynamic stays covered by the other regions.
  • New bench scenario inventory add or remove one.

Stacked on #719.

Measured on a local merge with #720 and #721, prebuilt binaries, 3 alternating rounds (Closures):

bench ui.dynamic ui.each
one row removed or added, of 200 686 µs 109 µs (−84%)
inventory search (162 of 200 rows change) 1.78 ms 1.72 ms
inventory mount or unmount 200 2.02 ms 2.05 ms

It only helps when most rows stay. What is left of the one row case is the list of 200 names itself: it crosses to Rust when computed, back to Lua for the title, and is keyed in Rust.

@semanticdiff-com

semanticdiff-com Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

@github-actions

github-actions Bot commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

🐰 Bencher Report

ProjectBevy Scripting
Branchagent/reactive-ui-each
Testbedlinux-gha

⚠️ WARNING: Truncated view!

The full continuous benchmarking report exceeds the maximum length allowed on this platform.

⚠️ WARNING: No Threshold found!

Without a Threshold, no Alerts will ever be generated.

🐰 View full continuous benchmarking report in Bencher

# Conflicts:
#	assets/benchmarks/reactive_ui/closures.lua
#	assets/benchmarks/reactive_ui/paths.lua
#	assets/tests/reactive_ui/inventory/inventory.lua
#	crates/bevy_mod_scripting_reactive_ui/src/lib.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