Skip to content

Column change detection for immutable components #18788

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 21 commits into
base: main
Choose a base branch
from

Conversation

notmd
Copy link
Contributor

@notmd notmd commented Apr 10, 2025

Objective

  • Implement column structure change detection for immutable component. This will allow to filter at table/archetype level for Query<(), Changed<SomeImmutableComponent>>

Solution

  • Adopt change from column/table level change detection #11120 but for column of immutable component only. This change doesn't need to store an atomic because immutable components can only be changed by inserting so performance overhead is minimal.
  • Add change_tick field to Column/ThinColumn. Change tick will be updated when inserting, replacing or removing elements. Updating when removing seems unnecessary because change detection doesn't detect removal. I am still updating it because I want to use this somehow to help implement query.is_changed(). We may consider introducing a separate tick for removal in the future.. Change tick will be update when inserting or replacing elements.

Testing

  • I have added a few new tests to test the archetype_filter_fetch
  • I also update the change detection benchmark for immutable component
  • Here the benchmark result for Query<Entity, Changed<T>>. You can reproduce this by running cargo bench -p benches --bench ecs -- --save-baseline current none_changed_detection and critcmp benches current -g '^(none_changed_detection/\d+\w+::\w+::[A-Z][a-z]+)'
    image
  • Unfortunately, I can't benchmark the overall ecs overhead on my laptop, too much noise. But I believe the overhead is very small. Really appreciate someone with good computer can verify my words.

Future work

  • Stop allocating changed_ticks for immutable component. Because it can't be mutated, use added_ticks for is enough.
  • Expand this to mutable components without hurting performance.

Copy link
Contributor

Your PR caused a change in the graphical output of an example or rendering test. This might be intentional, but it could also mean that something broke!
You can review it at https://pixel-eagle.com/project/B04F67C0-C054-4A6F-92EC-F599FEC2FD1D?filter=PR-18788

If it's expected, please add the M-Deliberate-Rendering-Change label.

If this change seems unrelated to your PR, you can consider updating your PR to target the latest main branch, either by rebasing or merging main into it.

@alice-i-cecile alice-i-cecile added C-Feature A new feature, making something new possible A-ECS Entities, components, systems, and events M-Needs-Release-Note Work that should be called out in the blog due to impact S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged labels Apr 10, 2025
Copy link
Contributor

It looks like your PR has been selected for a highlight in the next release blog post, but you didn't provide a release note.

Please review the instructions for writing release notes, then expand or revise the content in the release notes directory to showcase your changes.

@notmd notmd marked this pull request as ready for review April 11, 2025 15:51
@notmd
Copy link
Contributor Author

notmd commented Apr 11, 2025

I have no idea what miri is complaining. Help is appreciated.

@notmd
Copy link
Contributor Author

notmd commented Apr 11, 2025

Benchmark for update_ui_context_system, yellow is main, red is current branch in many_buttons. This is the only system I can find in Bevy that benefit from the changes. Maybe we can push for more immutable components in futures
cargo run --example many_buttons --release --features bevy/trace_tracy
image

@notmd notmd changed the title Column structure change detection Column change detection for immutable components Apr 13, 2025
@hymm hymm self-requested a review May 1, 2025 17:57
@kristoff3r kristoff3r added S-Needs-Review Needs reviewer attention (from anyone!) to move forward and removed S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged labels May 8, 2025
@@ -20,6 +20,7 @@ pub struct ThinColumn {
pub(super) added_ticks: ThinArrayPtr<UnsafeCell<Tick>>,
pub(super) changed_ticks: ThinArrayPtr<UnsafeCell<Tick>>,
pub(super) changed_by: MaybeLocation<ThinArrayPtr<UnsafeCell<&'static Location<'static>>>>,
change_tick: Tick,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can add a comment here? This is the change_tick associated with the most recent change in the table (i.e. of any row in the table)

@@ -170,18 +173,19 @@ impl ThinColumn {
&mut self,
row: TableRow,
data: OwningPtr<'_>,
change_tick: Tick,
tick: Tick,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think keeping this as change_tick was clearer

@@ -227,6 +232,7 @@ impl ThinColumn {
self_changed_by.initialize_unchecked(dst_row.as_usize(), changed_by);
},
);
self.change_tick = tick;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other values (added_ticks/change_ticks) were taken from the other ThinColumn, should we do the same for the Table-wide ChangeTick?

Or is this required for the correctness of archetype_filter_fetch?

Copy link
Contributor

@ElliottjPierce ElliottjPierce May 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like it might make the most sense to make both columns take the most recent of their change ticks. But IDK

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wdym table-wide ChangeTick? Currently, change tick only updated when an element is inserted or replaced. This is to reduce false positive of archetype_filter_fetch for Added and Changed. It's can be updated in more cases but not needed for now.

@@ -105,6 +105,18 @@ pub unsafe trait QueryFilter: WorldQuery {
entity: Entity,
table_row: TableRow,
) -> bool;

/// # Safety
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need extra comments to explain what this does.

Basically this is a way to filter/skip an entire table/archetype instead of an individual Entity or TableRow.
I would add something similar to the comment of filter_fetch and explain that currently this is mostly used as an optimization for non-archetypal filters such as Changed/Added

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree another comment would be good here. But this is brilliant btw.

@cBournhonesque
Copy link
Contributor

cBournhonesque commented May 8, 2025

The benchmarks you linked in the PR description are only for immutable components, right?
Do you have benchmarks for non-immutable components, and for general queries?

There's an extra function call in every query-iteration now

@alice-i-cecile alice-i-cecile added X-Controversial There is active debate or serious implications around merging this PR S-Needs-Benchmarking This set of changes needs performance benchmarking to double-check that they help labels May 8, 2025
@notmd
Copy link
Contributor Author

notmd commented May 8, 2025

The benchmarks you linked in the PR description are only for immutable components, right? Do you have benchmarks for non-immutable components, and for general queries?

There's an extra function call in every query-iteration now

I tried to run benchmark but it very noisy. The only overhead is size of ThinColumn/Column is now bigger. The extra function call should be compiled out. I will try to run the benchmark again tomorrow.

Copy link
Contributor

@ElliottjPierce ElliottjPierce left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. A few minor requests, but nothing blocking approval that I see.

I definitely would like benches here to see how this effects the rest of the ecs though. Maybe run them overnight?

@@ -227,6 +232,7 @@ impl ThinColumn {
self_changed_by.initialize_unchecked(dst_row.as_usize(), changed_by);
},
);
self.change_tick = tick;
Copy link
Contributor

@ElliottjPierce ElliottjPierce May 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like it might make the most sense to make both columns take the most recent of their change ticks. But IDK

@@ -105,6 +105,18 @@ pub unsafe trait QueryFilter: WorldQuery {
entity: Entity,
table_row: TableRow,
) -> bool;

/// # Safety
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree another comment would be good here. But this is brilliant btw.

@notmd
Copy link
Contributor Author

notmd commented May 10, 2025

Here is the benchmark. The result is kinda weird. all_added_detection has significant regression for table storage, but all_changed_detection shows no regression, even though they have very similar implementations. I rerun all_added_detection bench a few times and it has up to 20% diff

Click me
critcmp current main
group                                                                                                     current                                  main
-----                                                                                                     -------                                  ----
add_remove/sparse_set                                                                                     1.15  1185.7±26.95µs        ? ?/sec      1.00  1029.5±29.26µs        ? ?/sec
add_remove/table                                                                                          1.10  1416.2±49.54µs        ? ?/sec      1.00  1283.0±44.82µs        ? ?/sec
add_remove_big/sparse_set                                                                                 1.11  1290.4±18.86µs        ? ?/sec      1.00  1165.4±67.86µs        ? ?/sec
add_remove_big/table                                                                                      1.00      2.3±0.04ms        ? ?/sec      1.09      2.5±0.03ms        ? ?/sec
add_remove_very_big/table                                                                                 1.00     65.6±0.78ms        ? ?/sec      1.02     66.9±0.78ms        ? ?/sec
added_archetypes/archetype_count/100                                                                      1.00     42.4±0.60µs        ? ?/sec      1.03     43.7±1.53µs        ? ?/sec
added_archetypes/archetype_count/1000                                                                     1.00    736.7±7.45µs        ? ?/sec      1.06    778.5±4.74µs        ? ?/sec
added_archetypes/archetype_count/10000                                                                    1.00     15.7±0.23ms        ? ?/sec      1.02     15.9±0.20ms        ? ?/sec
all_added_detection/50000_entities_ecs::change_detection::Sparse                                          1.00     77.0±2.80µs        ? ?/sec      1.41    108.3±1.68µs        ? ?/sec
all_added_detection/50000_entities_ecs::change_detection::Table                                           1.42     92.0±3.43µs        ? ?/sec      1.00     64.6±3.50µs        ? ?/sec
all_added_detection/5000_entities_ecs::change_detection::Sparse                                           1.00      8.4±0.24µs        ? ?/sec      1.23     10.4±0.10µs        ? ?/sec
all_added_detection/5000_entities_ecs::change_detection::Table                                            1.37      9.1±0.57µs        ? ?/sec      1.00      6.7±0.16µs        ? ?/sec
all_changed_detection/50000_entities_ecs::change_detection::Sparse                                        1.11     90.6±1.80µs        ? ?/sec      1.00     81.2±2.59µs        ? ?/sec
all_changed_detection/50000_entities_ecs::change_detection::Table                                         1.00     63.4±3.04µs        ? ?/sec      1.01     64.1±6.42µs        ? ?/sec
all_changed_detection/5000_entities_ecs::change_detection::Sparse                                         1.00      8.3±0.36µs        ? ?/sec      1.11      9.2±0.17µs        ? ?/sec
all_changed_detection/5000_entities_ecs::change_detection::Table                                          1.00      5.8±0.29µs        ? ?/sec      1.02      5.9±0.25µs        ? ?/sec
build_schedule/1000_schedule                                                                              1.00       2.7±0.06s        ? ?/sec      1.00       2.7±0.02s        ? ?/sec
build_schedule/1000_schedule_no_constraints                                                               1.00     29.6±0.78ms        ? ?/sec      1.65     48.9±1.34ms        ? ?/sec
build_schedule/100_schedule                                                                               1.00      8.4±0.05ms        ? ?/sec      1.00      8.3±0.09ms        ? ?/sec
build_schedule/100_schedule_no_constraints                                                                1.02   615.2±13.35µs        ? ?/sec      1.00   604.4±14.20µs        ? ?/sec
build_schedule/500_schedule                                                                               1.02    386.3±9.55ms        ? ?/sec      1.00    380.2±8.08ms        ? ?/sec
build_schedule/500_schedule_no_constraints                                                                1.00      8.2±0.13ms        ? ?/sec      1.00      8.2±0.14ms        ? ?/sec
busy_systems/01x_entities_03_systems                                                                      1.20     52.8±3.65µs        ? ?/sec      1.00     44.1±2.21µs        ? ?/sec
busy_systems/01x_entities_09_systems                                                                      1.09    123.9±9.53µs        ? ?/sec      1.00    113.8±7.96µs        ? ?/sec
busy_systems/01x_entities_15_systems                                                                      1.22   213.8±12.37µs        ? ?/sec      1.00    175.5±7.56µs        ? ?/sec
busy_systems/03x_entities_03_systems                                                                      1.00     81.6±3.50µs        ? ?/sec      1.08     88.4±8.34µs        ? ?/sec
busy_systems/03x_entities_09_systems                                                                      1.00   234.2±15.53µs        ? ?/sec      1.14   266.4±20.22µs        ? ?/sec
busy_systems/03x_entities_15_systems                                                                      1.00   399.4±24.45µs        ? ?/sec      1.07   427.9±25.72µs        ? ?/sec
busy_systems/05x_entities_03_systems                                                                      1.03   115.1±14.25µs        ? ?/sec      1.00    111.2±7.61µs        ? ?/sec
busy_systems/05x_entities_09_systems                                                                      1.10   356.1±36.52µs        ? ?/sec      1.00   322.8±21.50µs        ? ?/sec
busy_systems/05x_entities_15_systems                                                                      1.13   606.8±30.87µs        ? ?/sec      1.00   539.0±21.07µs        ? ?/sec
contrived/01x_entities_03_systems                                                                         1.00     27.5±1.77µs        ? ?/sec      1.03     28.2±2.05µs        ? ?/sec
contrived/01x_entities_09_systems                                                                         1.06     78.1±3.69µs        ? ?/sec      1.00     73.9±5.92µs        ? ?/sec
contrived/01x_entities_15_systems                                                                         1.07    126.4±7.89µs        ? ?/sec      1.00    118.5±4.29µs        ? ?/sec
contrived/03x_entities_03_systems                                                                         1.00     40.9±3.81µs        ? ?/sec      1.01     41.3±4.62µs        ? ?/sec
contrived/03x_entities_09_systems                                                                         1.01    132.2±4.56µs        ? ?/sec      1.00    131.5±8.58µs        ? ?/sec
contrived/03x_entities_15_systems                                                                         1.00   193.5±14.54µs        ? ?/sec      1.02   197.4±10.92µs        ? ?/sec
contrived/05x_entities_03_systems                                                                         1.00     50.6±5.07µs        ? ?/sec      1.00     50.5±4.85µs        ? ?/sec
contrived/05x_entities_09_systems                                                                         1.00    163.2±9.66µs        ? ?/sec      1.16   188.7±62.86µs        ? ?/sec
contrived/05x_entities_15_systems                                                                         1.00   256.8±17.38µs        ? ?/sec      1.15   294.2±25.11µs        ? ?/sec
despawn_world/10000_entities                                                                              1.05   628.5±15.87µs        ? ?/sec      1.00   597.9±14.50µs        ? ?/sec
despawn_world/100_entities                                                                                1.00      7.3±0.22µs        ? ?/sec      1.06      7.7±0.25µs        ? ?/sec
despawn_world/1_entities                                                                                  1.00   338.6±32.40ns        ? ?/sec      1.00   338.8±32.69ns        ? ?/sec
despawn_world_recursive/10000_entities                                                                    1.00      3.1±0.02ms        ? ?/sec      1.03      3.2±0.05ms        ? ?/sec
despawn_world_recursive/100_entities                                                                      1.00     32.4±1.43µs        ? ?/sec      1.00     32.4±1.18µs        ? ?/sec
despawn_world_recursive/1_entities                                                                        1.00   646.8±47.74ns        ? ?/sec      1.10   711.4±35.91ns        ? ?/sec
ecs::entity_cloning::hierarchy_many/clone                                                                 1.00   273.9±45.52µs 1297.6 KElem/sec    1.01   277.0±49.20µs 1283.3 KElem/sec
ecs::entity_cloning::hierarchy_many/reflect                                                               1.00   566.4±26.37µs 627.6 KElem/sec     1.04   589.8±44.72µs 602.6 KElem/sec
ecs::entity_cloning::hierarchy_tall/clone                                                                 1.00    18.6±35.96µs  2.6 MElem/sec      1.00    18.6±35.44µs  2.6 MElem/sec
ecs::entity_cloning::hierarchy_tall/reflect                                                               1.00    23.4±44.21µs  2.1 MElem/sec      1.00    23.3±28.96µs  2.1 MElem/sec
ecs::entity_cloning::hierarchy_wide/clone                                                                 1.00     12.4±0.79µs  3.9 MElem/sec      1.11     13.8±0.68µs  3.5 MElem/sec
ecs::entity_cloning::hierarchy_wide/reflect                                                               1.11     18.0±0.55µs  2.7 MElem/sec      1.00     16.2±0.93µs  3.0 MElem/sec
ecs::entity_cloning::single/clone                                                                         1.00   666.4±85.08ns 1465.4 KElem/sec    1.12  748.9±173.00ns 1304.1 KElem/sec
ecs::entity_cloning::single/reflect                                                                       1.07  1563.3±51.13ns 624.7 KElem/sec     1.00  1460.7±68.93ns 668.6 KElem/sec
empty_archetypes/for_each/10                                                                              1.02      8.2±0.78µs        ? ?/sec      1.00      8.0±0.64µs        ? ?/sec
empty_archetypes/for_each/100                                                                             1.03      8.4±0.89µs        ? ?/sec      1.00      8.2±0.95µs        ? ?/sec
empty_archetypes/for_each/1000                                                                            1.04      8.9±0.90µs        ? ?/sec      1.00      8.6±0.59µs        ? ?/sec
empty_archetypes/for_each/10000                                                                           1.11     16.6±1.86µs        ? ?/sec      1.00     15.0±1.03µs        ? ?/sec
empty_archetypes/iter/10                                                                                  1.00      7.8±0.28µs        ? ?/sec      1.00      7.8±0.30µs        ? ?/sec
empty_archetypes/iter/100                                                                                 1.07      8.7±1.20µs        ? ?/sec      1.00      8.1±0.86µs        ? ?/sec
empty_archetypes/iter/1000                                                                                1.00      8.3±0.50µs        ? ?/sec      1.08      8.9±1.38µs        ? ?/sec
empty_archetypes/iter/10000                                                                               1.00     14.3±1.38µs        ? ?/sec      1.13     16.1±1.61µs        ? ?/sec
empty_archetypes/par_for_each/10                                                                          1.01     11.4±1.22µs        ? ?/sec      1.00     11.3±1.32µs        ? ?/sec
empty_archetypes/par_for_each/100                                                                         1.00     11.6±1.05µs        ? ?/sec      1.05     12.1±1.12µs        ? ?/sec
empty_archetypes/par_for_each/1000                                                                        1.01     15.9±0.91µs        ? ?/sec      1.00     15.8±0.70µs        ? ?/sec
empty_archetypes/par_for_each/10000                                                                       1.01     28.3±2.20µs        ? ?/sec      1.00     28.1±1.29µs        ? ?/sec
empty_commands/0_entities                                                                                 1.03      6.8±0.06ns        ? ?/sec      1.00      6.6±0.27ns        ? ?/sec
empty_systems/0_systems                                                                                   1.12      7.4±0.09ns        ? ?/sec      1.00      6.6±0.07ns        ? ?/sec
empty_systems/1000_systems                                                                                1.00   761.1±33.46µs        ? ?/sec      1.00   759.5±39.40µs        ? ?/sec
empty_systems/100_systems                                                                                 1.00     82.4±2.89µs        ? ?/sec      1.01     82.9±1.90µs        ? ?/sec
empty_systems/10_systems                                                                                  1.00     11.6±0.57µs        ? ?/sec      1.00     11.5±0.51µs        ? ?/sec
empty_systems/2_systems                                                                                   1.02      8.4±0.59µs        ? ?/sec      1.00      8.2±0.66µs        ? ?/sec
empty_systems/4_systems                                                                                   1.00      9.0±0.69µs        ? ?/sec      1.06      9.5±0.90µs        ? ?/sec
entity_hash/entity_set_build/100                                                                          1.03   651.9±35.18ns 146.3 MElem/sec     1.00   630.3±36.85ns 151.3 MElem/sec
entity_hash/entity_set_build/1000                                                                         1.00      5.5±0.33µs 174.7 MElem/sec     1.00      5.5±0.24µs 174.9 MElem/sec
entity_hash/entity_set_build/10000                                                                        1.08     63.6±3.37µs 149.9 MElem/sec     1.00     58.8±6.32µs 162.2 MElem/sec
entity_hash/entity_set_build/316                                                                          1.11  1978.9±27.28ns 152.3 MElem/sec     1.00  1789.8±58.89ns 168.4 MElem/sec
entity_hash/entity_set_build/3162                                                                         1.16     19.3±0.87µs 156.3 MElem/sec     1.00     16.7±1.59µs 181.0 MElem/sec
entity_hash/entity_set_lookup_hit/100                                                                     1.00    197.5±7.52ns 482.8 MElem/sec     1.03    203.5±1.89ns 468.6 MElem/sec
entity_hash/entity_set_lookup_hit/1000                                                                    1.04      2.2±0.04µs 431.4 MElem/sec     1.00      2.1±0.08µs 447.9 MElem/sec
entity_hash/entity_set_lookup_hit/10000                                                                   1.06     32.3±0.96µs 294.9 MElem/sec     1.00     30.4±1.21µs 313.7 MElem/sec
entity_hash/entity_set_lookup_hit/316                                                                     1.06    708.4±8.08ns 425.4 MElem/sec     1.00   668.7±26.68ns 450.7 MElem/sec
entity_hash/entity_set_lookup_hit/3162                                                                    1.05      7.6±0.28µs 396.5 MElem/sec     1.00      7.3±0.28µs 415.3 MElem/sec
entity_hash/entity_set_lookup_miss_gen/100                                                                1.02   297.7±11.64ns 320.4 MElem/sec     1.00    290.4±9.13ns 328.4 MElem/sec
entity_hash/entity_set_lookup_miss_gen/1000                                                               1.01      2.9±0.12µs 325.4 MElem/sec     1.00      2.9±0.12µs 327.8 MElem/sec
entity_hash/entity_set_lookup_miss_gen/10000                                                              1.00     76.2±3.18µs 125.1 MElem/sec     1.05     80.0±2.63µs 119.3 MElem/sec
entity_hash/entity_set_lookup_miss_gen/316                                                                1.00  1036.0±40.62ns 290.9 MElem/sec     1.05  1083.6±45.94ns 278.1 MElem/sec
entity_hash/entity_set_lookup_miss_gen/3162                                                               1.00     27.2±1.92µs 110.9 MElem/sec     1.28     34.9±1.52µs 86.4 MElem/sec
entity_hash/entity_set_lookup_miss_id/100                                                                 1.01    202.3±4.48ns 471.4 MElem/sec     1.00    199.6±4.05ns 477.7 MElem/sec
entity_hash/entity_set_lookup_miss_id/1000                                                                1.00      2.1±0.05µs 453.7 MElem/sec     1.02      2.1±0.11µs 445.4 MElem/sec
entity_hash/entity_set_lookup_miss_id/10000                                                               1.00     68.3±2.40µs 139.6 MElem/sec     1.02     69.8±3.19µs 136.7 MElem/sec
entity_hash/entity_set_lookup_miss_id/316                                                                 1.00   735.7±32.00ns 409.6 MElem/sec     1.01   741.1±63.75ns 406.7 MElem/sec
entity_hash/entity_set_lookup_miss_id/3162                                                                1.00     32.2±1.56µs 93.6 MElem/sec      1.04     33.4±1.10µs 90.2 MElem/sec
event_propagation/four_event_types                                                                        1.00    644.9±9.25µs        ? ?/sec      1.22   785.6±54.64µs        ? ?/sec
event_propagation/single_event_type                                                                       1.00   721.7±20.55µs        ? ?/sec      1.28   921.7±29.79µs        ? ?/sec
event_propagation/single_event_type_no_listeners                                                          1.00    418.3±9.04µs        ? ?/sec      1.08   450.3±24.66µs        ? ?/sec
events_iter/size_16_events_100                                                                            1.01     99.2±5.12ns        ? ?/sec      1.00     98.3±5.23ns        ? ?/sec
events_iter/size_16_events_1000                                                                           1.05   965.0±26.46ns        ? ?/sec      1.00   918.9±27.91ns        ? ?/sec
events_iter/size_16_events_10000                                                                          1.05      9.5±0.37µs        ? ?/sec      1.00      9.1±0.37µs        ? ?/sec
events_iter/size_4_events_100                                                                             1.00    100.3±5.48ns        ? ?/sec      1.00     99.9±2.77ns        ? ?/sec
events_iter/size_4_events_1000                                                                            1.05   968.6±41.13ns        ? ?/sec      1.00   919.6±24.71ns        ? ?/sec
events_iter/size_4_events_10000                                                                           1.04      9.6±0.43µs        ? ?/sec      1.00      9.2±1.17µs        ? ?/sec
events_iter/size_512_events_100                                                                           1.22    119.4±5.94ns        ? ?/sec      1.00     97.8±4.20ns        ? ?/sec
events_iter/size_512_events_1000                                                                          1.19  1131.0±33.77ns        ? ?/sec      1.00   948.4±37.30ns        ? ?/sec
events_iter/size_512_events_10000                                                                         1.27     11.6±0.33µs        ? ?/sec      1.00      9.1±0.32µs        ? ?/sec
events_send/size_16_events_100                                                                            1.00    146.2±3.80ns        ? ?/sec      1.29    188.4±2.32ns        ? ?/sec
events_send/size_16_events_1000                                                                           1.00  1978.0±82.02ns        ? ?/sec      1.08      2.1±0.04µs        ? ?/sec
events_send/size_16_events_10000                                                                          1.00     21.5±1.46µs        ? ?/sec      1.03     22.2±0.94µs        ? ?/sec
events_send/size_4_events_100                                                                             1.00    125.3±1.09ns        ? ?/sec      1.48    185.8±7.45ns        ? ?/sec
events_send/size_4_events_1000                                                                            1.00   1270.1±8.43ns        ? ?/sec      1.53  1944.7±89.36ns        ? ?/sec
events_send/size_4_events_10000                                                                           1.00     15.9±0.81µs        ? ?/sec      1.12     17.9±0.57µs        ? ?/sec
events_send/size_512_events_100                                                                           1.07      2.7±0.03µs        ? ?/sec      1.00      2.5±0.13µs        ? ?/sec
events_send/size_512_events_1000                                                                          1.07     30.3±0.26µs        ? ?/sec      1.00     28.3±0.99µs        ? ?/sec
events_send/size_512_events_10000                                                                         1.00   314.8±34.37µs        ? ?/sec      1.05   330.5±23.35µs        ? ?/sec
fake_commands/10000_commands                                                                              1.13     97.0±1.37µs        ? ?/sec      1.00     85.9±3.30µs        ? ?/sec
fake_commands/1000_commands                                                                               1.05      9.7±0.15µs        ? ?/sec      1.00      9.2±0.08µs        ? ?/sec
fake_commands/100_commands                                                                                1.14  1001.4±11.72ns        ? ?/sec      1.00   879.2±46.90ns        ? ?/sec
few_changed_detection/50000_entities_ecs::change_detection::Sparse                                        1.01    100.0±4.07µs        ? ?/sec      1.00     99.0±2.50µs        ? ?/sec
few_changed_detection/50000_entities_ecs::change_detection::Table                                         1.00     73.2±1.55µs        ? ?/sec      1.11     81.1±1.28µs        ? ?/sec
few_changed_detection/5000_entities_ecs::change_detection::Sparse                                         1.40      8.9±0.11µs        ? ?/sec      1.00      6.4±0.29µs        ? ?/sec
few_changed_detection/5000_entities_ecs::change_detection::Table                                          1.00      6.4±0.09µs        ? ?/sec      1.28      8.3±0.08µs        ? ?/sec
heavy_compute/base                                                                                        1.05   420.1±25.58µs        ? ?/sec      1.00   398.2±23.72µs        ? ?/sec
insert_commands/insert                                                                                    1.11   758.1±29.99µs        ? ?/sec      1.00   683.5±39.72µs        ? ?/sec
insert_commands/insert_batch                                                                              1.10   348.5±12.40µs        ? ?/sec      1.00   317.5±20.20µs        ? ?/sec
insert_simple/base                                                                                        1.00    311.7±3.04µs        ? ?/sec      1.05    326.1±2.82µs        ? ?/sec
insert_simple/unbatched                                                                                   1.00    668.9±7.82µs        ? ?/sec      1.02    680.1±8.34µs        ? ?/sec
iter_fragmented(4096)_empty/foreach_sparse                                                                1.00     14.7±0.25µs        ? ?/sec      1.01     14.7±0.32µs        ? ?/sec
iter_fragmented(4096)_empty/foreach_table                                                                 1.00      4.5±0.09µs        ? ?/sec      1.32      6.0±0.12µs        ? ?/sec
iter_fragmented/base                                                                                      1.00    569.3±9.87ns        ? ?/sec      1.01   575.1±30.34ns        ? ?/sec
iter_fragmented/foreach                                                                                   1.00   213.8±19.14ns        ? ?/sec      1.03   219.4±23.39ns        ? ?/sec
iter_fragmented/foreach_wide                                                                              1.00      4.9±0.16µs        ? ?/sec      1.03      5.0±0.19µs        ? ?/sec
iter_fragmented/wide                                                                                      1.04      6.8±0.11µs        ? ?/sec      1.00      6.6±0.16µs        ? ?/sec
iter_fragmented_sparse/base                                                                               1.16     10.3±0.20ns        ? ?/sec      1.00      8.9±0.48ns        ? ?/sec
iter_fragmented_sparse/foreach                                                                            1.01     10.2±0.33ns        ? ?/sec      1.00     10.1±0.31ns        ? ?/sec
iter_fragmented_sparse/foreach_wide                                                                       1.00     53.6±1.40ns        ? ?/sec      1.04     55.9±2.15ns        ? ?/sec
iter_fragmented_sparse/wide                                                                               1.00     66.1±2.74ns        ? ?/sec      1.01     67.1±2.66ns        ? ?/sec
iter_simple/base                                                                                          1.00     11.1±0.10µs        ? ?/sec      1.37     15.3±0.15µs        ? ?/sec
iter_simple/foreach                                                                                       1.26     13.0±0.17µs        ? ?/sec      1.00     10.3±0.27µs        ? ?/sec
iter_simple/foreach_hybrid                                                                                1.00     14.0±0.23µs        ? ?/sec      1.08     15.1±0.26µs        ? ?/sec
iter_simple/foreach_sparse_set                                                                            1.03     23.0±0.89µs        ? ?/sec      1.00     22.3±0.29µs        ? ?/sec
iter_simple/foreach_wide                                                                                  1.39     60.3±1.01µs        ? ?/sec      1.00     43.4±1.74µs        ? ?/sec
iter_simple/foreach_wide_sparse_set                                                                       1.00    120.0±3.34µs        ? ?/sec      1.06    126.8±2.26µs        ? ?/sec
iter_simple/sparse_set                                                                                    1.06     27.3±0.42µs        ? ?/sec      1.00     25.8±1.11µs        ? ?/sec
iter_simple/system                                                                                        1.06     10.9±0.54µs        ? ?/sec      1.00     10.3±0.32µs        ? ?/sec
iter_simple/wide                                                                                          1.00     51.8±1.56µs        ? ?/sec      1.05     54.5±0.66µs        ? ?/sec
iter_simple/wide_sparse_set                                                                               1.00    115.1±2.78µs        ? ?/sec      1.04    120.2±3.08µs        ? ?/sec
multiple_archetypes_none_changed_detection/100_archetypes_10000_entities_ecs::change_detection::Sparse    1.02  1778.2±47.24µs        ? ?/sec      1.00  1742.9±55.55µs        ? ?/sec
multiple_archetypes_none_changed_detection/100_archetypes_10000_entities_ecs::change_detection::Table     1.00   600.8±61.96µs        ? ?/sec      1.04   623.1±31.91µs        ? ?/sec
multiple_archetypes_none_changed_detection/100_archetypes_1000_entities_ecs::change_detection::Sparse     1.02    137.9±5.05µs        ? ?/sec      1.00    135.2±9.50µs        ? ?/sec
multiple_archetypes_none_changed_detection/100_archetypes_1000_entities_ecs::change_detection::Table      1.03     64.0±6.85µs        ? ?/sec      1.00     62.0±4.02µs        ? ?/sec
multiple_archetypes_none_changed_detection/100_archetypes_100_entities_ecs::change_detection::Sparse      1.03     13.4±0.29µs        ? ?/sec      1.00     13.0±0.30µs        ? ?/sec
multiple_archetypes_none_changed_detection/100_archetypes_100_entities_ecs::change_detection::Table       1.13      9.4±0.37µs        ? ?/sec      1.00      8.3±0.32µs        ? ?/sec
multiple_archetypes_none_changed_detection/100_archetypes_10_entities_ecs::change_detection::Sparse       1.00  1823.6±65.41ns        ? ?/sec      1.04  1890.4±63.40ns        ? ?/sec
multiple_archetypes_none_changed_detection/100_archetypes_10_entities_ecs::change_detection::Table        1.00  1936.6±82.95ns        ? ?/sec      1.00  1936.6±58.91ns        ? ?/sec
multiple_archetypes_none_changed_detection/20_archetypes_10000_entities_ecs::change_detection::Sparse     1.00   309.7±10.35µs        ? ?/sec      1.04   322.9±10.70µs        ? ?/sec
multiple_archetypes_none_changed_detection/20_archetypes_10000_entities_ecs::change_detection::Table      1.00    112.2±6.06µs        ? ?/sec      1.00    111.6±6.25µs        ? ?/sec
multiple_archetypes_none_changed_detection/20_archetypes_1000_entities_ecs::change_detection::Sparse      1.12     21.1±0.38µs        ? ?/sec      1.00     18.9±0.43µs        ? ?/sec
multiple_archetypes_none_changed_detection/20_archetypes_1000_entities_ecs::change_detection::Table       1.61     16.0±0.40µs        ? ?/sec      1.00      9.9±0.28µs        ? ?/sec
multiple_archetypes_none_changed_detection/20_archetypes_100_entities_ecs::change_detection::Sparse       1.02      2.3±0.06µs        ? ?/sec      1.00      2.3±0.35µs        ? ?/sec
multiple_archetypes_none_changed_detection/20_archetypes_100_entities_ecs::change_detection::Table        1.31  1922.8±91.59ns        ? ?/sec      1.00  1465.0±74.92ns        ? ?/sec
multiple_archetypes_none_changed_detection/20_archetypes_10_entities_ecs::change_detection::Sparse        1.10   420.7±24.93ns        ? ?/sec      1.00   383.7±15.21ns        ? ?/sec
multiple_archetypes_none_changed_detection/20_archetypes_10_entities_ecs::change_detection::Table         1.10   348.2±61.19ns        ? ?/sec      1.00   315.9±19.47ns        ? ?/sec
multiple_archetypes_none_changed_detection/5_archetypes_10000_entities_ecs::change_detection::Sparse      1.03     52.6±1.19µs        ? ?/sec      1.00     51.1±1.22µs        ? ?/sec
multiple_archetypes_none_changed_detection/5_archetypes_10000_entities_ecs::change_detection::Table       1.29     33.5±0.75µs        ? ?/sec      1.00     26.0±0.55µs        ? ?/sec
multiple_archetypes_none_changed_detection/5_archetypes_1000_entities_ecs::change_detection::Sparse       1.00      5.0±0.73µs        ? ?/sec      1.09      5.4±0.10µs        ? ?/sec
multiple_archetypes_none_changed_detection/5_archetypes_1000_entities_ecs::change_detection::Table        1.23      3.5±0.13µs        ? ?/sec      1.00      2.9±0.04µs        ? ?/sec
multiple_archetypes_none_changed_detection/5_archetypes_100_entities_ecs::change_detection::Sparse        1.06   689.0±28.96ns        ? ?/sec      1.00   651.4±15.43ns        ? ?/sec
multiple_archetypes_none_changed_detection/5_archetypes_100_entities_ecs::change_detection::Table         1.27   509.6±12.16ns        ? ?/sec      1.00   400.0±22.38ns        ? ?/sec
multiple_archetypes_none_changed_detection/5_archetypes_10_entities_ecs::change_detection::Sparse         1.02   127.4±24.94ns        ? ?/sec      1.00    125.0±7.30ns        ? ?/sec
multiple_archetypes_none_changed_detection/5_archetypes_10_entities_ecs::change_detection::Table          1.00   103.4±10.58ns        ? ?/sec      1.05    108.4±6.98ns        ? ?/sec
no_archetypes/system_count/0                                                                              1.00     12.2±0.29ns        ? ?/sec      1.04     12.7±0.09ns        ? ?/sec
no_archetypes/system_count/10                                                                             1.00    192.0±5.05ns        ? ?/sec      1.03    197.9±1.97ns        ? ?/sec
no_archetypes/system_count/100                                                                            1.03  1757.2±18.16ns        ? ?/sec      1.00  1705.7±17.65ns        ? ?/sec
none_changed_detection/50000_entities_ecs::change_detection::Sparse                                       1.00     52.3±4.88µs        ? ?/sec      1.47     76.6±6.05µs        ? ?/sec
none_changed_detection/50000_entities_ecs::change_detection::SparseImmutable                              1.00     55.4±6.28ns        ? ?/sec    
none_changed_detection/50000_entities_ecs::change_detection::Table                                        1.10     37.6±0.70µs        ? ?/sec      1.00     34.3±1.58µs        ? ?/sec
none_changed_detection/50000_entities_ecs::change_detection::TableImmutable                               1.00     59.8±5.88ns        ? ?/sec    
none_changed_detection/5000_entities_ecs::change_detection::Sparse                                        1.00      5.2±0.08µs        ? ?/sec      1.52      7.9±0.21µs        ? ?/sec
none_changed_detection/5000_entities_ecs::change_detection::SparseImmutable                               1.00     30.9±0.83ns        ? ?/sec    
none_changed_detection/5000_entities_ecs::change_detection::Table                                         1.00      3.8±0.06µs        ? ?/sec      1.02      3.9±0.03µs        ? ?/sec
none_changed_detection/5000_entities_ecs::change_detection::TableImmutable                                1.00     37.0±5.89ns        ? ?/sec    
observe/trigger_simple                                                                                    1.00   337.9±17.57µs        ? ?/sec      1.17    394.5±7.85µs        ? ?/sec
observe/trigger_targets_simple/10000_entity                                                               1.00  884.1±204.91µs        ? ?/sec      1.04  922.7±125.43µs        ? ?/sec
par_iter_simple/hybrid                                                                                    1.02    107.6±8.07µs        ? ?/sec      1.00    105.9±7.68µs        ? ?/sec
par_iter_simple/with_0_fragment                                                                           1.01    61.3±11.84µs        ? ?/sec      1.00     60.5±5.64µs        ? ?/sec
par_iter_simple/with_1000_fragment                                                                        1.00     76.9±5.49µs        ? ?/sec      1.01     77.9±4.66µs        ? ?/sec
par_iter_simple/with_100_fragment                                                                         1.00     68.1±4.00µs        ? ?/sec      1.01     68.6±2.87µs        ? ?/sec
par_iter_simple/with_10_fragment                                                                          1.00     66.5±3.92µs        ? ?/sec      1.01     67.0±5.12µs        ? ?/sec
param/combinator_system/8_dyn_params_system                                                               1.04     20.1±4.23µs        ? ?/sec      1.00     19.4±2.25µs        ? ?/sec
param/combinator_system/8_piped_systems                                                                   1.00      8.3±0.39µs        ? ?/sec      1.02      8.4±0.51µs        ? ?/sec
param/combinator_system/8_variant_param_set_system                                                        1.00     10.7±2.10µs        ? ?/sec      1.08     11.6±2.60µs        ? ?/sec
query_get/50000_entities_sparse                                                                           1.00   284.9±12.38µs        ? ?/sec      1.01    289.0±4.78µs        ? ?/sec
query_get/50000_entities_table                                                                            1.00    262.7±9.67µs        ? ?/sec      1.32    346.6±7.81µs        ? ?/sec
query_get_many_10/50000_calls_sparse                                                                      1.00      5.0±0.08ms        ? ?/sec      1.04      5.2±0.08ms        ? ?/sec
query_get_many_10/50000_calls_table                                                                       1.00      3.9±0.12ms        ? ?/sec      1.04      4.0±0.16ms        ? ?/sec
query_get_many_2/50000_calls_sparse                                                                       1.00   530.8±43.50µs        ? ?/sec      1.25   661.4±25.09µs        ? ?/sec
query_get_many_2/50000_calls_table                                                                        1.00   523.5±20.14µs        ? ?/sec      1.20   628.7±16.01µs        ? ?/sec
query_get_many_5/50000_calls_sparse                                                                       1.00  1688.4±189.65µs        ? ?/sec     1.02  1715.0±89.79µs        ? ?/sec
query_get_many_5/50000_calls_table                                                                        1.00  1303.6±205.13µs        ? ?/sec     1.07  1395.7±93.88µs        ? ?/sec
run_condition/no/1000_systems                                                                             1.22     59.8±0.49µs        ? ?/sec      1.00     49.0±1.85µs        ? ?/sec
run_condition/no/100_systems                                                                              1.18      4.2±0.03µs        ? ?/sec      1.00      3.5±0.14µs        ? ?/sec
run_condition/no/10_systems                                                                               1.03   444.3±22.64ns        ? ?/sec      1.00   430.6±24.82ns        ? ?/sec
run_condition/yes/1000_systems                                                                            1.02   736.8±26.13µs        ? ?/sec      1.00   723.0±32.05µs        ? ?/sec
run_condition/yes/100_systems                                                                             1.00     78.1±4.83µs        ? ?/sec      1.02     79.4±5.36µs        ? ?/sec
run_condition/yes/10_systems                                                                              1.00     11.0±0.78µs        ? ?/sec      1.01     11.2±0.82µs        ? ?/sec
run_condition/yes_using_query/1000_systems                                                                1.02   742.3±28.31µs        ? ?/sec      1.00   728.6±30.83µs        ? ?/sec
run_condition/yes_using_query/100_systems                                                                 1.02     80.0±4.26µs        ? ?/sec      1.00     78.5±4.32µs        ? ?/sec
run_condition/yes_using_query/10_systems                                                                  1.03     11.2±0.61µs        ? ?/sec      1.00     10.8±1.33µs        ? ?/sec
run_condition/yes_using_resource/1000_systems                                                             1.00   754.0±24.96µs        ? ?/sec      1.00   752.8±30.25µs        ? ?/sec
run_condition/yes_using_resource/100_systems                                                              1.00     81.5±3.04µs        ? ?/sec      1.00     81.5±2.97µs        ? ?/sec
run_condition/yes_using_resource/10_systems                                                               1.00     11.7±0.73µs        ? ?/sec      1.00     11.7±0.60µs        ? ?/sec
run_empty_schedule/MultiThreaded                                                                          1.21      7.3±0.36ns        ? ?/sec      1.00      6.1±0.25ns        ? ?/sec
run_empty_schedule/Simple                                                                                 1.12      8.4±0.31ns        ? ?/sec      1.00      7.5±0.30ns        ? ?/sec
run_empty_schedule/SingleThreaded                                                                         1.02     11.6±0.41ns        ? ?/sec      1.00     11.4±0.42ns        ? ?/sec
schedule/base                                                                                             1.00     44.2±3.06µs        ? ?/sec      1.05     46.5±1.91µs        ? ?/sec
sized_commands_0_bytes/10000_commands                                                                     1.00     81.6±3.59µs        ? ?/sec      1.08     87.8±0.64µs        ? ?/sec
sized_commands_0_bytes/1000_commands                                                                      1.19      9.0±0.08µs        ? ?/sec      1.00      7.6±0.37µs        ? ?/sec
sized_commands_0_bytes/100_commands                                                                       1.15   889.6±11.25ns        ? ?/sec      1.00   776.3±28.76ns        ? ?/sec
sized_commands_12_bytes/10000_commands                                                                    1.00     91.2±4.00µs        ? ?/sec      1.07     97.7±1.83µs        ? ?/sec
sized_commands_12_bytes/1000_commands                                                                     1.07      9.4±0.16µs        ? ?/sec      1.00      8.7±0.40µs        ? ?/sec
sized_commands_12_bytes/100_commands                                                                      1.01   940.3±10.20ns        ? ?/sec      1.00   933.9±23.62ns        ? ?/sec
sized_commands_512_bytes/10000_commands                                                                   1.01   358.0±49.57µs        ? ?/sec      1.00   354.0±60.69µs        ? ?/sec
sized_commands_512_bytes/1000_commands                                                                    1.00     31.6±1.12µs        ? ?/sec      1.05     33.0±1.04µs        ? ?/sec
sized_commands_512_bytes/100_commands                                                                     1.01      2.9±0.05µs        ? ?/sec      1.00      2.9±0.06µs        ? ?/sec
spawn_commands/10000_entities                                                                             1.00  1135.9±57.38µs        ? ?/sec      1.06  1202.4±31.92µs        ? ?/sec
spawn_commands/1000_entities                                                                              1.02    111.0±6.22µs        ? ?/sec      1.00    108.6±5.70µs        ? ?/sec
spawn_commands/100_entities                                                                               1.03     11.7±0.62µs        ? ?/sec      1.00     11.4±0.30µs        ? ?/sec
spawn_world/10000_entities                                                                                1.07  967.5±249.19µs        ? ?/sec      1.00  907.6±197.41µs        ? ?/sec
spawn_world/100_entities                                                                                  1.00      8.7±2.50µs        ? ?/sec      1.01      8.8±2.14µs        ? ?/sec
spawn_world/1_entities                                                                                    1.00    89.1±25.79ns        ? ?/sec      1.01    89.7±22.21ns        ? ?/sec
world_entity/50000_entities                                                                               1.00   340.6±11.38µs        ? ?/sec      1.01   342.4±15.09µs        ? ?/sec
world_get/50000_entities_sparse                                                                           1.00   274.6±16.39µs        ? ?/sec      1.11    305.2±5.89µs        ? ?/sec
world_get/50000_entities_table                                                                            1.00   300.0±12.33µs        ? ?/sec      1.00   301.2±10.39µs        ? ?/sec
world_query_for_each/50000_entities_sparse                                                                1.00     73.7±0.91µs        ? ?/sec      1.05     77.2±0.76µs        ? ?/sec
world_query_for_each/50000_entities_table                                                                 1.01     23.5±0.36µs        ? ?/sec      1.00     23.3±0.61µs        ? ?/sec
world_query_get/50000_entities_sparse                                                                     1.00    169.7±4.84µs        ? ?/sec      1.21    206.1±2.72µs        ? ?/sec
world_query_get/50000_entities_sparse_wide                                                                1.15    195.9±3.40µs        ? ?/sec      1.00    170.7±8.18µs        ? ?/sec
world_query_get/50000_entities_table                                                                      1.00    166.0±3.93µs        ? ?/sec      1.02    169.7±2.62µs        ? ?/sec
world_query_get/50000_entities_table_wide                                                                 1.04    172.1±5.25µs        ? ?/sec      1.00    164.8±3.24µs        ? ?/sec
world_query_iter/50000_entities_sparse                                                                    1.00     61.3±0.77µs        ? ?/sec      1.02     62.6±0.87µs        ? ?/sec
world_query_iter/50000_entities_table                                                                     1.00     24.3±0.76µs        ? ?/sec      1.48     35.9±0.52µs        ? ?/sec

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ECS Entities, components, systems, and events C-Feature A new feature, making something new possible M-Needs-Release-Note Work that should be called out in the blog due to impact S-Needs-Benchmarking This set of changes needs performance benchmarking to double-check that they help S-Needs-Review Needs reviewer attention (from anyone!) to move forward X-Controversial There is active debate or serious implications around merging this PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants