ReactiveUI

Performance

Reactive V2 against V1 and BSML, in BeatLeader and in stress tests, on PC and Quest.

We measured BeatLeader's own UI on Reactive V1 and V2, then ran the same stress tests on V1, V2 and BSML on PC, and on Reactive and BSML on Quest 3.

  • BeatLeader: UI time is unchanged, and V1's memory leak is gone.
  • V2 vs V1: V2 mounts about 4× faster. Its layout lead comes from a faster Yoga build, not from Reactive. State is far faster in the worst cases, while single writes are slower.
  • Reactive vs BSML: Reactive is much faster when part of a big UI changes, and usually mounts faster. BSML is faster when many labels change text, and when moving things without layout.

Each bar shows how many times better one side is, on a log scale. No bar means the difference is within noise. A * marks a row where the two sides don't do the same work or weren't measured the same way, with a note under its group. Don't compare PC numbers with Quest numbers.

BeatLeader

V1 → V2
V1 betterV2 better
Main menu, UI time per frame7.38 → 8.04 mssame
Playing a replay, UI time per frame11.1 → 11.9 mssame
Opening the hub, longest frame108 → 87.9 mssame
Opening the leaderboard, longest frame1385 → 1415 mssame
Memory kept by each replay after the first14.9 → ≤3.0 MB>4.9× less

V1 never frees the Yoga nodes of destroyed Images, Labels and list rows, or anything they reference, so its memory grows for as long as the game runs.

V2 vs V1

V1 → V2
V1 betterV2 better
Layout
No layout engine, parent resizes16.9 → 18.8 ms1.1× slower
1000 flex items, one resizes13.3 → 3.67 ms3.6× faster
500 percent-sized items, root resizes18.4 → 11.5 ms1.6× faster
128 nested containers, innermost resizes19.7 → 2.64 ms7.5× faster
Tree of 1365 growing nodes44.8 → 25.0 ms1.8× faster
300 labels, all change text*42.2 → 35.1 ms1.2× faster

* V1 sets each label's text directly. V2 writes 300 bound states, the way BeatLeader's V2 UI does.

State
One write, one callback2.0 → 7.4 µs3.6× slower
One write, 1000 callbacks74.1 → 38.6 µs1.9× faster
Callbacks writing more states, 6 levels304 → 667 µs2.2× slower
1000 writes per frame, 100 callbacks*730 → 29.3 µs25× faster
1000 subscribes and unsubscribes**5.78 ms → 82.2 µs70× faster
18 stacked diamonds*20.0 ms → 26.7 µs750× faster

* Not the same work: V1 calls back on every write, 100000 times per frame in the burst and 262144 times at the end of the diamonds. V2 runs each callback once per flush, with the latest value.

** V1 has no subscription handle, so this uses its C# event, which copies the whole list of callbacks on every add and remove.

Animation
2000 Images, color33.9 → 31.9 ms1.1× faster
64 flex panels, size and color25.4 → 12.6 ms2.0× faster
Lists
Table of 100000, scrolling8.34 → 8.07 mssame
Flat list of 500 rows, all rebind*275 → 107 ms2.6× faster
Flat list growing by 10 rows per frame*91.7 → 14.4 ms6.4× faster

* V1 ran each of these in a fresh game session, because its leak slows down everything after it, while V2 ran the full suite. So this is V1's best case.

Mounting
1000 Images*320 → 71.8 ms4.5× faster
1000 Labels*865 → 224 ms3.9× faster
500 list rows*1104 → 291 ms3.8× faster
Creating and destroying 50 rows per frame*124 → 31.0 ms4.0× faster

* Also from a fresh V1 session each.

Memory
100000 states18.2 → 24.2 MB1.3× more
5000 animated boxes17.0 → 6.79 MB2.5× less
2000 list rows*82.5 → 73.4 MB1.1× less

* Also from a fresh V1 session.

Single writes, chains of maps and states writing each other are slower because V2 compares the value, queues the state and notifies on flush. That's also what makes bursts cheap, and they all stay under a millisecond.

Is the layout gain Reactive or Yoga?

V1 ships with an unoptimized yoga.dll, and V2 was measured on a Release build. With both on the Release build:

V1 → V2
V1 betterV2 better
Layout
1000 flex items, one resizes3.03 → 2.87 mssame
1000 flex items, root resizes3.28 → 5.23 ms1.6× slower
128 nested containers, innermost resizes1.06 → 1.81 mssame
Tree of 1365 growing nodes24.9 → 26.8 mssame
Mounting
1000 Images*312 → 71.8 ms4.3× faster
1000 Labels*764 → 224 ms3.4× faster
500 list rows*1204 → 291 ms4.1× faster

* V1 ran each of these in a fresh game session, V2 in the full suite.

V1 catches up on layout and is up to 1.6× faster in some cases, but its mounts stay slow. So the layout gain comes from the Yoga build, and the mount gain from Reactive.

Reactive vs BSML

BSML can't always do the same work, see where the work differs.

PC

BSML → V2
BSML betterV2 better
Layout
1000 items, one resizes*12.5 → 3.67 ms3.4× faster
Tree of 1365 nodes, fixed-size leaves34.9 → 5.81 ms6.0× faster
Tree of 1365 growing nodes35.7 → 25.0 ms1.4× faster
300 labels, all change text**20.1 → 35.1 ms1.8× slower

* BSML uses 40 rows of 25, because its layout groups can't wrap items of different sizes. Reactive wraps all 1000 in one container.

** BSML uses 30 rows of 10 and sets each text directly. Reactive wraps all 300 in one container and writes 300 bound states.

State
500 labels showing one value*19.9 → 54.9 ms2.8× slower

* BSML's labels sit in grid cells of a fixed size, so their text isn't measured for layout, while Reactive's are sized by their text.

Animation
2000 Images, color*30.5 → 31.9 mssame
500 items, position only**≈0 → 3.15 ms>1.6× slower

* BSML has no animations, so a hand-written loop works out one value per frame and sets it on every item. Reactive runs a separate animation per item.

** The same loop, and BSML's items ignore layout, so moving them only writes their transforms. Reactive moves absolute flex items, so its layout runs every frame.

Lists
Table of 100000, jumping far*126 → 7.78 ms16× faster
Flat list of 2000 rows, idle15.2 → 21.3 ms1.4× slower
Flat list of 500 rows, all rebind**89.8 → 107 ms1.2× slower

* BSML's custom-list creates and parses a new cell whenever a row comes into view, instead of reusing one. That's BSML's own behavior.

** BSML has no list to give new items to, so each row's bound object is updated in place. Reactive's list gets a new array of items.

Mounting
1000 Images*556 → 71.8 ms7.8× faster
1000 Labels*623 → 224 ms2.8× faster
500 list rows*1444 → 291 ms5.0× faster
Creating and destroying 50 rows per frame*121 → 31.0 ms3.9× faster

* BSML parses its markup on every mount, where Reactive builds from code. BSML also places the first three in a grid of fixed cells rather than wrapping them, so its 1000 Labels aren't measured for layout.

Memory
5000 animated boxes*21.0 → 6.79 MB3.1× less
2000 list rows120 → 73.4 MB1.6× less

* BSML has no animations, so its 5000 Images hold no animation state, while Reactive's hold one each.

Quest 3

BSML → Reactive
BSML betterReactive better
Layout
1000 items, one resizes*29.5 → 0.77 ms38× faster
Tree of 1365 nodes, fixed-size leaves73.0 → 3.63 ms20× faster
Tree of 1365 growing nodes74.4 → 38.0 ms2.0× faster
300 labels, all change text**24.6 → 27.9 ms1.1× slower

* BSML uses 40 rows of 25, because its layout groups can't wrap items of different sizes. Reactive wraps all 1000 in one container.

** BSML uses 30 rows of 10 and sets each text directly. Reactive wraps all 300 in one container and writes 300 bound states.

State
500 labels showing one value*20.7 → 44.7 ms2.2× slower

* Quest BSML has no change notifications, so the loop sets all 500 labels by hand. Its labels also sit in grid cells of a fixed size, so their text isn't measured for layout, while Reactive's are sized by their text.

Animation
2000 Images, color*52.6 → 55.3 ms1.1× slower
500 items, position only**0.09 → 1.50 ms17× slower

* BSML has no animations, so a hand-written loop works out one value per frame and sets it on every item. Reactive runs a separate animation per item.

** The same loop, and BSML's items ignore layout, so moving them only writes their transforms. Reactive moves absolute flex items, so its layout runs every frame.

Lists
Flat list of 2000 rows, idle1.35 → 5.24 ms3.9× slower
Flat list of 500 rows, all rebind*126 → 87.7 ms1.4× faster

* Quest BSML has no change notifications, so the loop sets all 1000 labels by hand. Reactive's list gets a new array of items.

Mounting
1000 Images*279 → 173 ms1.6× faster
1000 Labels*716 → 808 ms1.1× slower
500 list rows*1224 → 1033 ms1.2× faster
Creating and destroying 50 rows per frame*129 → 112 ms1.2× faster

* BSML parses its markup on every mount, where Reactive builds from code. BSML also places the first three in a grid of fixed cells rather than wrapping them, so its 1000 Labels aren't measured for layout.

Memory
5000 animated boxes*6.41 → 14.1 MB2.2× more
2000 list rows83.7 → 90.6 MB1.1× more

* BSML has no animations, so its 5000 Images hold no animation state, while Reactive's hold one each.

reactive-quest has no Table, so the table row is missing here.

How it was measured

Measured on 2026-11-05 with the benchmarks in Tests/UIHarness of the BeatLeader repository. Its README has the commands.

UI time is main thread time per frame over idle, as a p50. State benchmarks are timed directly. Mounts are the median mount after the first, including its first 6 frames. Memory is the managed heap with the benchmark mounted, plus the native heap on Quest.

Setup and caveats
  • UI time window: from the first Update to the end of Canvas.willRenderCanvases.
  • Same: the ranges over all rounds overlap, or the gap is under 5% or under the noise floor of an empty benchmark, which is 0.66 ms on V1 and V2, 1.95 ms on BSML and 0.03 ms on Quest.
  • PC: Beat Saber 1.44.0, Ryzen 7 5800H, RTX 3070 Laptop, in FPFC on a hidden desktop, which makes absolute numbers higher than usual. V1 is Reactive 859fe5d, V2 is Reactive 56b3941 with a Release yoga.dll, BSML is 1.14.1. 3 rounds of V2 and BSML, 2 of V1. BeatLeader ran 2 rounds per version, and its main menu 5 sessions.
  • Quest: Beat Saber 1.40.8 on Quest 3 at 120 Hz, with no thermal throttling. reactive-quest 743aba6 and BSML 0.4.55, 3 rounds each.
  • Same work: V1, V2 and Quest Reactive end with matching layouts, apart from animations, tables and state-subscribe. BSML can't match them, so we compared screenshots of every benchmark instead.
  • Not covered: PC VR, other machines and GPU cost.

Where the work differs

Each target is written the way its library is normally used: V2 the way BeatLeader's UI is, V1 with its own API, and BSML with markup and ~value bindings. Where that changes the work, or a target was measured differently, the chart row has a * and a note under its group.

Every difference

V1 and V2

  • Fresh sessions for V1: V1's leak slows down everything after it, so its mounts, flat lists, life-churn and ram-rows each ran in a game session of their own, while V2 ran the full suite. That's V1's best case. V1's mounts on V2's Yoga also come from one session each, and its layout there from 2 rounds.
  • Callbacks: V1 calls back on every write. That's 100000 calls per frame in state-burst and 262144 at the end of state-diamond-deep, where V2 runs each callback once per flush. So these rows show V2 doing less work by design.
  • Subscribing: V1 has no subscription handle, so state-subscribe uses its C# event, which copies the whole list of callbacks on every add and remove.
  • Text: V1 sets label text directly, and V2 writes bound states, so V2's text benchmarks include its state work.

BSML

  • No wrapping: UGUI's layout groups can't wrap items of different sizes, so where one item changes size, BSML uses rows of a fixed length with the same number of items. Elsewhere a grid of fixed cells stands in for wrapping, so BSML's labels in life-label and state-labels aren't measured for layout, while Reactive's are. This helps BSML.
  • No animations: a hand-written loop works out one value per frame and sets it on every item, while Reactive runs one animation per item. That's about the least work a BSML view could do, not a library feature. In anim-position, BSML's items also ignore layout, so only their transforms move, while Reactive's absolute flex items run layout every frame. In ram-animated, BSML's Images hold no animation state. All of this helps BSML.
  • Markup: BSML parses markup on every mount, including all 50 rows per frame in life-churn. That's how BSML builds UI, so it's counted.
  • Tables on PC: CustomCellListTableData.CellForIdx creates a GameObject and parses the cell again whenever a row comes into view, instead of reusing one. That's BSML's own behavior, and Quest BSML reuses its cells.
  • No list component: in list-flat-shuffle, each row's bound object is updated in place, while Reactive's list gets a new array of items.
  • No change notifications on Quest: state-labels and list-flat-shuffle set the labels by hand there, which skips binding entirely. This helps BSML.
  • No state system: state-labels is the only state benchmark with a BSML version, and ram-state is left out.

All numbers

Show all numbers

UI time, p50. Milliseconds per frame over idle. State benchmarks are timed directly.

BenchmarkCaseV1V2BSMLQuest ReactiveQuest BSML
layout-rect
No layout engine: 1000 anchored Images, parent resized every frame
best16.918.817.529.128.6
layout-idle
1000 flex items mounted, nothing changes
best1.861.69≈00.190.04
layout-panels
40 fixed-size panels of 25 items: one item changes size inside one panel every frame
best4.582.8115.10.3735.9
layout-leaf
Fixed-size flex: one of 1000 items changes size every frame
average13.33.6712.50.7729.5
layout-root
Fixed-size flex: 1000 items, the root resized every frame
worst13.43.783.992.547.58
layout-tree-fixed
The same tree with fixed-size leaves, so nothing is measured, the root resized every frame
worst20.35.8134.93.6373.0
layout-percent
Percent-sized and growing flex: 500 items, the root resized every frame
average18.411.513.717.328.0
layout-tree
Tree of nested growing flex containers (1365 nodes), the root resized every frame
worst44.825.035.738.074.4
layout-text-one
Text-measured flex: one of 300 labels changes its text every frame
average3.231.474.470.488.78
layout-rows
Column of 200 list rows (800 nodes), the root resized every frame
average29.520.015.321.930.2
layout-text-all
Text-measured flex: all 300 labels change their text every frame
worst42.235.120.127.924.6
layout-tree-text
Tree of content-sized containers with text leaves (364 nodes): text and root change every frame
worst57.019.215.419.823.8
layout-deep
128 nested flex containers, the innermost item changes size every frame
worst19.72.645.931.9112.7
layout-absolute
500 absolutely positioned flex items all move every frame
average5.223.46≈00.71≈0
layout-toggle
Half of 200 list rows hide and show every frame
worst17.714.719.18.9022.3
state-labels
One write per frame updates the text of 500 bound labels through a map
worst70.654.919.944.720.7
state-single
One state, one callback, one write per frame
best2.0 µs7.4 µs–6.0 µs–
state-same-value
1000 writes of the same value per frame, one callback
best11.9 µs8.8 µs–3.1 µs–
state-fanout
One write per frame reaches 1000 callbacks
average74.1 µs38.6 µs–25.1 µs–
state-chain
Callbacks in callbacks: a chain of 100 maps
average10.7 µs30.1 µs–29.9 µs–
state-burst
1000 writes per frame with 100 callbacks
worst730 µs29.3 µs–14.3 µs–
state-reentrant
Callbacks in callbacks: two states write each other 200 times per frame
worst17.6 µs53.2 µs–41.3 µs–
state-cascade
Callbacks in callbacks: each callback writes four more states, six levels deep (5461 writes)
worst304 µs667 µs–384 µs–
state-diamond
Callbacks in callbacks: 14 stacked diamonds, where one write reaches the end by 16384 paths
worst1.25 ms22.8 µs–20.8 µs–
state-diamond-deep
Callbacks in callbacks: 18 stacked diamonds, where one write reaches the end by 262144 paths
worst20.0 ms26.7 µs–24.7 µs–
state-subscribe
1000 subscribes and unsubscribes per frame on a state with 1000 callbacks
worst5.78 ms82.2 µs–4.06 ms–
anim-color-small
100 Images animating their color
best0.691.19≈02.642.34
anim-position
500 absolute items animating their position
average5.283.15≈01.500.09
anim-color-large
2000 Images animating their color, so no layout
average33.931.930.555.352.6
anim-size
200 flex items animating their size, so layout every frame
worst5.484.305.197.7811.9
anim-retarget
1000 color animations restarted every frame
worst17.716.315.828.525.9
anim-storm
Nested flex dashboard: 64 panels of 4 boxes animating size and color, plus a label changing text every frame
worst25.412.613.818.726.9
list-table-idle
Virtualized table with 100000 items, nothing changes
best0.98≈0≈0–0.23
list-table-scroll
Virtualized table with 100000 items, scrolled by a row every frame
average8.348.076.63–1.08
list-table-jump
Virtualized table with 100000 items, jumping far every frame so every cell rebinds
worst7.747.78126–14.6
list-table-refresh
Virtualized table with 10000 items, replaced by a filtered list every frame
worst9.748.44119–13.8
list-flat-idle
Flat list of 2000 rows (8000 nodes), nothing changes
average27.321.315.25.241.35
list-flat-shuffle
Flat list of 500 rows, all shifted by one every frame so every row rebinds
worst27510789.887.7126
list-flat-grow
Flat list growing by 10 rows every frame
worst91.714.437.324.449.6
life-layout-noflex
Mount and destroy 1000 empty Layouts in a parent without a layout controller
best1.27≈0≈00.25-0.09
life-layout
Mount and destroy 1000 empty Layouts
best1.79≈0≈00.22-0.09
life-image
Mount and destroy 1000 Images
average5.081.21≈00.21-0.10
life-label
Mount and destroy 1000 Labels
average1.801.97≈00.510.31
life-row
Mount and destroy 500 list rows (background, icon, two labels)
worst4.335.132.161.060.34
life-append
Mount and destroy 4000 empty Layouts in one container, to show how appending scales against life-layout
worst4.563.166.280.880.05
life-churn
Create and destroy 50 rows every frame
worst12431.0121112129
ram-state
100000 states with one callback each
best2.28-1.07–-0.16–
ram-animated
5000 boxes with a color animation each
average11.09.813.551.010.36
ram-rows
2000 list rows (8000 nodes)
worst24.219.611.44.361.24

UI time, p99.

BenchmarkV1V2BSMLQuest ReactiveQuest BSML
layout-rect29.630.029.731.530.3
layout-idle7.186.777.201.080.50
layout-panels14.810.229.30.9038.6
layout-leaf21.48.8636.71.1832.4
layout-root24.711.414.13.579.02
layout-tree-fixed33.813.657.74.6677.9
layout-percent29.419.826.719.530.4
layout-tree63.542.758.640.878.8
layout-text-one10.36.6012.61.1010.9
layout-rows45.433.428.424.732.4
layout-text-all60.554.233.529.927.4
layout-tree-text85.333.426.922.526.8
layout-deep29.97.5311.63.1914.1
layout-absolute12.410.85.771.360.48
layout-toggle46.133.542.731.850.1
state-labels10188.434.064.326.9
state-single3.9 µs13.8 µs–10.5 µs–
state-same-value20.0 µs15.1 µs–7.2 µs–
state-fanout180 µs71.0 µs–55.9 µs–
state-chain19.0 µs70.3 µs–76.2 µs–
state-burst1.12 ms44.3 µs–31.7 µs–
state-reentrant42.9 µs102 µs–83.6 µs–
state-cascade606 µs1.21 ms–533 µs–
state-diamond1.60 ms38.0 µs–68.2 µs–
state-diamond-deep25.0 ms42.7 µs–78.4 µs–
state-subscribe268 ms134 µs–5.01 ms–
anim-color-small5.276.406.013.694.00
anim-position12.610.65.362.611.28
anim-color-large52.052.048.060.357.4
anim-size13.112.012.212.815.9
anim-retarget28.928.528.130.428.4
anim-storm37.924.824.826.329.3
list-table-idle5.654.435.19–0.62
list-table-scroll16.517.916.8–1.74
list-table-jump15.715.9392–16.6
list-table-refresh15.217.9411–15.9
list-flat-idle17634.427.16.332.70
list-flat-shuffle46814914393.2131
list-flat-grow21364.874.369.673.8
life-layout-noflex3.583.252.130.450.18
life-layout2.942.612.490.560.12
life-image6.813.354.000.440.11
life-label5.195.913.611.110.59
life-row8.629.516.971.640.71
life-append9.976.4411.11.050.24
life-churn385151299136154
ram-state3.920.66–0.09–
ram-animated12.314.86.401.440.49
ram-rows45.528.418.34.942.21

Mount, ms.

BenchmarkV1V2BSMLQuest ReactiveQuest BSML
layout-rect79.566.2582368579
layout-idle76570.0551172279
layout-panels145392.2765186451
layout-leaf98798.7600178363
layout-root71874.2705176267
layout-tree-fixed1414138745249496
layout-percent47743.323189.8174
layout-tree1158120813262500
layout-text-one53095.4170251259
layout-rows820130663434538
layout-text-all70583.4181242247
layout-tree-text45762.1210237254
layout-deep35.314.843221.21483
layout-absolute112636.824190.9175
layout-toggle1790115562420536
state-labels1303118237439330
state-single11.82.06–0.68–
state-same-value3.283.72–0.43–
state-fanout3.5716.7–0.76–
state-chain11.41.99–0.27–
state-burst3.362.99–0.28–
state-reentrant6.674.32–0.23–
state-cascade8.005.92–2.79–
state-diamond13.85.59–0.84–
state-diamond-deep5.5010.8–0.50–
state-subscribe7.782.10–0.48–
anim-color-small35715.639.124.431.2
anim-position68145.4316106171
anim-color-large28821671094400564
anim-size27217.695.142.472.5
anim-retarget132388.4554202282
anim-storm56862.3259135217
list-table-idle27535.8147–232
list-table-scroll25830.4130–218
list-table-jump20626.2120–203
list-table-refresh22933.8110–116
list-flat-idle46401823615348675867
list-flat-shuffle952407156311101334
list-flat-grow17.90.174.390.570.89
life-layout-noflex28.726.052757.9122
life-layout40.925.865161.7234
life-image32071.8556173279
life-label865224623808716
life-row1104291144410331224
life-append25410222382581046
life-churn7.935.809.010.551.73
ram-state18023.5–50.9–
ram-animated27266441267210061505
ram-rows33971412586543415703

Memory while mounted, MB.

BenchmarkV1V2BSMLQuest ReactiveQuest BSML
layout-rect0.820.213.700.941.11
layout-idle1.930.483.791.190.40
layout-panels1.760.204.071.660.99
layout-leaf1.950.463.791.620.81
layout-root1.900.413.701.610.76
layout-tree-fixed2.570.544.192.101.23
layout-percent0.50≈00.720.770.39
layout-tree2.720.554.232.111.22
layout-text-one7.296.148.54≈07.70
layout-rows8.024.9512.77.787.05
layout-text-all7.416.068.547.987.71
layout-tree-text3.381.854.383.513.26
layout-deep≈0≈0≈00.150.16
layout-absolute0.16≈00.52≈00.60
layout-toggle7.904.9712.87.747.07
state-labels8.0110.510.213.55.85
state-single≈0≈0–≈0–
state-same-value≈0≈0–≈0–
state-fanout≈0≈0–0.19–
state-chain≈0≈0–≈0–
state-burst≈0≈0–≈0–
state-reentrant≈0≈0–≈0–
state-cascade≈0≈0–1.01–
state-diamond≈0≈0–≈0–
state-diamond-deep≈0≈0–≈0–
state-subscribe≈0≈0–0.19–
anim-color-small≈0≈0≈00.220.11
anim-position0.10≈00.551.350.54
anim-color-large5.891.454.455.212.03
anim-size≈0≈0≈00.510.20
anim-retarget1.870.103.542.450.80
anim-storm0.63≈01.621.871.15
list-table-idle1.030.554.46–18.5
list-table-scroll1.170.474.44–19.1
list-table-jump1.130.454.43–18.1
list-table-refresh0.330.121.45–4.90
list-flat-idle125117166127116
list-flat-shuffle27.325.156.031.527.5
list-flat-grow≈0≈0≈0≈0≈0
life-layout-noflex0.520.431.451.130.17
life-layout0.700.486.181.120.42
life-image1.990.914.021.650.80
life-label22.019.121.523.614.1
life-row20.615.227.221.118.7
life-append5.593.4211.14.712.15
life-churn≈0≈0≈0≈0≈0
ram-state18.224.2–27.5–
ram-animated17.06.7921.014.16.41
ram-rows82.573.412090.683.7

Memory left after destroying, MB.

BenchmarkManaged left: V1V2BSMLYoga nodes left: V1V2
life-image
Mount and destroy 1000 Images
1.940010010
life-label
Mount and destroy 1000 Labels
21.900.0710010
life-row
Mount and destroy 500 list rows (background, icon, two labels)
20.500.0720010
life-churn
Create and destroy 50 rows every frame
22800214010
list-flat-idle
Flat list of 2000 rows (8000 nodes), nothing changes
1250080020
list-flat-shuffle
Flat list of 500 rows, all shifted by one every frame so every row rebinds
27.90020020
list-flat-grow
Flat list growing by 10 rows every frame
23.30016820
ram-rows
2000 list rows (8000 nodes)
82.30080010

Memory per component.

ComponentV1V2BSMLQuest ReactiveQuest BSML
Image1.1 KB942 B4.1 KB1.8 KB947 B
Label20.2 KB19.4 KB21.9 KB24.4 KB14.5 KB
Empty container750 B557 B6.3 KB1.2 KB488 B
List row (background, icon, two labels)35.1 KB31.1 KB55.1 KB43.4 KB39.0 KB

Allocated per frame. Benchmarks at 10 KB or more on any PC target. Only accurate to a heap block.

BenchmarkV1V2BSML
state-subscribe24227 KB0.0 KB–
life-churn2257 KB1645 KB10702 KB
list-table-refresh0.5 KB0.0 KB5756 KB
list-table-jump0.8 KB0.1 KB4796 KB
list-flat-grow844 KB606 KB2936 KB
list-flat-shuffle411 KB18 KB16 KB
list-table-scroll3.5 KB2.5 KB286 KB
layout-absolute0.7 KB146 KB0.1 KB
state-labels47 KB72 KB45 KB
layout-tree-text51 KB24 KB20 KB
layout-rows28 KB19 KB0.3 KB
layout-rect17 KB2.1 KB1.9 KB
layout-text-one4.8 KB4.6 KB12 KB
layout-toggle11 KB1.6 KB0.0 KB

BeatLeader, time.

WhereMetricV1, msV2, msResult
Main menu, idleUI CPU, p507.388.04same
Main menu, idleUI CPU, mean7.878.36same
Main menu, idleUI CPU, p9912.414.1same
Main menu, idleWhole frame, p509.099.65same
Playing a replayUI CPU, p5011.111.9same
Playing a replayUI CPU, mean11.912.4same
Playing a replayUI CPU, p9923.820.0same
Playing a replayWhole frame, p5011.712.5same

BeatLeader, opening screens. Longest frame in milliseconds.

ScreenFirst open: V1V2Later opens: V1V2Result, first open
Hub10887.932.623.6same
Settings41.341.638.425.9same
Replay manager51552231.552.1same
Leaderboard13851415107109same

BeatLeader, memory.

WhereMetricV1V2
Main menuManaged heap134 MB136 MB
Main menuUnity allocator1447 MB1448 MB
Main menuProcess private bytes3038 MB3043 MB
Main menuLive Yoga nodes432423
HubManaged kept by the first open0.39 MB0.17 MB
SettingsManaged kept by the first open0.45 MB0.55 MB
Replay managerManaged kept by the first open2.15 MB2.07 MB
LeaderboardManaged kept by the first open58.1 MB70.6 MB
ReplayManaged kept by the first replay37.3 to 37.8 MB36.2 to 42.3 MB
ReplayManaged kept by each later replay14.9 to 15.6 MBat most 3.0 MB
ReplayYoga nodes kept by each replay3370

V1 on V2's Yoga, layout. Milliseconds per frame.

BenchmarkV1V1 on V2's YogaV2V1 on V2's Yoga vs V1V2 vs V1 on V2's Yoga
layout-leaf14.53.032.874.8× fastersame
layout-root14.23.285.234.3× faster1.6× slower
layout-percent18.110.314.91.8× faster1.4× slower
layout-deep21.31.061.8120× fastersame
layout-tree-fixed23.77.188.693.3× faster1.2× slower
layout-tree47.024.926.81.9× fastersame
layout-rows35.819.421.01.8× faster1.1× slower

V1 on V2's Yoga, mounts. Milliseconds.

BenchmarkV1V1 on V2's YogaV2
life-layout
Mount and destroy 1000 empty Layouts
40.943.725.8
life-image
Mount and destroy 1000 Images
32031271.8
life-label
Mount and destroy 1000 Labels
865764224
life-row
Mount and destroy 500 list rows (background, icon, two labels)
11041204291
life-append
Mount and destroy 4000 empty Layouts in one container, to show how appending scales against life-layout
254148102
ram-rows
2000 list rows (8000 nodes)
339747121412

On this page