Skip to content

chore: Add benchmarks covering the component tree hot paths#3959

Merged
spydon merged 5 commits into
mainfrom
bench/fcs-core-benchmarks
Jul 22, 2026
Merged

chore: Add benchmarks covering the component tree hot paths#3959
spydon merged 5 commits into
mainfrom
bench/fcs-core-benchmarks

Conversation

@spydon

@spydon spydon commented Jul 21, 2026

Copy link
Copy Markdown
Member

Description

Adds the benchmark coverage needed to evaluate new component tree implementations (#3957), so that every phase of that work can be measured against a locked-in baseline.

New suites

  • children_traversal_benchmark.dart: pure update-pass and render-pass overhead (container iteration, updateTree/renderTree recursion) over no-op components in four tree shapes: wide (10k x 1), nested (1k x 10), deep (100 levels), and a barrier tree where every 10th parent overrides updateTree via HasTimeScale. The barrier variant exists because effects, routes, and time-scaled components manage their own subtree traversal, so it is the realistic go/no-go input for flattened-traversal designs.
  • component_churn_benchmark.dart: steady-state add/remove churn (100 components per tick through the lifecycle queue) at both 1k and 10k populations, plus bulk 1k add/remove cycles. The 10k variant exists because removal cost inside one large sibling container scales differently per container implementation.
  • priority_change_benchmark.dart: single-child priority changes across 100 parents (today a full sibling rebalance each), and the y-sort pattern where all 1000 children of one container are re-prioritized every tick. Random sequences are precomputed in setup so every run() does identical work.
  • type_query_benchmark.dart: maintenance and read cost of the register<T>()/query<T>() type-query caches under mixed-type churn, since any container replacement must keep that surface.
  • common.dart: a mountGame helper that brings a FlameGame to a properly loaded and mounted state without a GameWidget.
  • README.md: how to run the suite, what each file measures, and pitfalls when writing new benchmarks.

Fixes to existing benchmarks

  • update_components_benchmark.dart never called onGameResize/load/mount, so hasLayout was false, onLoad never ran, and the intended 10 children per component were never created: it silently measured a flat tree of ~1000 empty components (11x smaller than intended) with the lifecycle queue bypassed. It now mounts properly; ticks were reduced from 2000 to 500 (same input density) so the harness gets ~12 samples per measurement window instead of ~3.
  • render_components_benchmark.dart now also mounts properly, and both older files got a top-level main so they can be run standalone.
  • main.dart now runs every suite in the directory, including the previously unwired hit-testing and collision benchmarks.

Baseline on a desktop machine (JIT, asserts on, relative comparison only)

Benchmark RunTime
Update / Render wide tree (10k x 1) 8.9 ms / 13.4 ms
Update / Render nested tree (1k x 10) 17.7 ms / 24.1 ms
Update / Render deep tree (100 levels) 18.1 ms / 27.3 ms
Update barrier tree (1k x 10, 10% time-scaled) 17.8 ms
Lifecycle churn (100 per tick, 1k / 10k population) 4.8 ms / 10.4 ms
Mass add/remove (1k per cycle) 3.2 ms
Priority change (1 child per parent) 64.9 ms
Priority change (y-sort, 1k children) 22.6 ms
Type-query churn (2 registered queries) 6.8 ms

Not covered here and left as follow-up: a GC/allocation-rate measurement (needs a different harness than benchmark_harness) and on-device AOT runs, which is how go/no-go numbers for #3957 should be collected (flutter run --release -t benchmark/main.dart).

Checklist

  • I have followed the Contributor Guide when preparing my PR.
  • [-] I have updated/added tests for ALL new/updated/fixed functionality.
  • I have updated/added relevant documentation in docs and added dartdoc comments with ///.
  • [-] I have updated/added relevant examples in examples or docs.

Breaking Change?

  • Yes, this PR is a breaking change.
  • No, this PR is not a breaking change.

Related Issues

Related to #3957

spydon added 4 commits July 19, 2026 18:19
 - flame@1.38.0
 - flame_3d@0.3.0
 - flame_behaviors@1.4.0
 - flame_bloc@1.12.24
 - flame_steering_behaviors@0.2.2+6
 - flame_test@2.3.0
 - flame_tiled@3.1.2
 - flame_behavior_tree@0.1.5+5
 - flame_gamepads@0.1.2
 - flame_isolate@0.6.3+23
 - flame_texturepacker@5.1.2
 - flame_sprite_fusion@0.2.4+2
 - flame_fire_atlas@1.8.18
 - flame_audio@2.12.2
 - flame_spine@0.3.1+6
 - flame_kenney_xml@0.1.3+2
 - flame_lottie@0.4.3+23
 - flame_markdown@0.2.5+16
 - flame_console@0.1.4
 - flame_rive@1.11.2
 - flame_forge2d@0.19.3+7
 - flame_noise@0.3.3+23
 - flame_riverpod@5.5.5
 - flame_svg@1.12.2
 - flame_typled@0.1.2
 - flame_network_assets@0.3.4+23
@spydon
spydon merged commit 3c33170 into main Jul 22, 2026
8 checks passed
@spydon
spydon deleted the bench/fcs-core-benchmarks branch July 22, 2026 07:32
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.

2 participants