From 9ca92dd892ea4cc17a778b966af78fdd28674e76 Mon Sep 17 00:00:00 2001 From: Trashtalk Date: Sat, 2 May 2026 15:13:46 +0200 Subject: [PATCH] store resources on sparse sets --- benches/benches/bevy_ecs/main.rs | 2 + benches/benches/bevy_ecs/resources.rs | 69 +++++++++++++++++++++++++ crates/bevy_ecs/macros/src/component.rs | 2 +- 3 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 benches/benches/bevy_ecs/resources.rs diff --git a/benches/benches/bevy_ecs/main.rs b/benches/benches/bevy_ecs/main.rs index 9e59d31aca00c..ec3447549f0cb 100644 --- a/benches/benches/bevy_ecs/main.rs +++ b/benches/benches/bevy_ecs/main.rs @@ -15,6 +15,7 @@ mod fragmentation; mod iteration; mod observers; mod param; +mod resources; mod scheduling; mod world; @@ -28,6 +29,7 @@ criterion_main!( iteration::benches, fragmentation::benches, observers::benches, + resources::benches, scheduling::benches, world::benches, param::benches, diff --git a/benches/benches/bevy_ecs/resources.rs b/benches/benches/bevy_ecs/resources.rs new file mode 100644 index 0000000000000..736e5daaeeb50 --- /dev/null +++ b/benches/benches/bevy_ecs/resources.rs @@ -0,0 +1,69 @@ +use std::{alloc::Layout, hint::black_box, ptr::NonNull}; + +use benches::bench; +use bevy_ecs::{ + change_detection::MaybeLocation, + component::{ComponentCloneBehavior, ComponentDescriptor, StorageType}, + prelude::*, + ptr::OwningPtr, +}; +use criterion::{criterion_group, Criterion}; + +criterion_group!(benches, get, get_mut, insert_remove); + +fn create_world() -> World { + let mut world = World::new(); + for _ in 0..500 { + // SAFETY: Uses zero-sized value, never drops + unsafe { + let resource_id = + world.register_component_with_descriptor(ComponentDescriptor::new_with_layout( + "", + StorageType::SparseSet, + Layout::new::<()>(), + None, + true, + ComponentCloneBehavior::Default, + None, + )); + world.insert_resource_by_id( + resource_id, + OwningPtr::new(NonNull::dangling()), + MaybeLocation::caller(), + ); + } + } + world +} + +#[derive(Resource)] +struct R; + +pub fn get(criterion: &mut Criterion) { + let mut world = create_world(); + world.insert_resource(R); + criterion.bench_function(bench!("get"), |bencher| { + bencher.iter(|| world.get_resource::()); + }); +} + +pub fn get_mut(criterion: &mut Criterion) { + let mut world = create_world(); + world.insert_resource(R); + criterion.bench_function(bench!("get_mut"), |bencher| { + bencher.iter(|| { + black_box(world.get_resource_mut::()); + }); + }); +} + +pub fn insert_remove(criterion: &mut Criterion) { + let mut world = create_world(); + criterion.bench_function(bench!("insert_remove"), |bencher| { + bencher.iter(|| { + world.insert_resource(R); + black_box(&mut world); + world.remove_resource::() + }); + }); +} diff --git a/crates/bevy_ecs/macros/src/component.rs b/crates/bevy_ecs/macros/src/component.rs index 66e9244f44c68..142aea76ba8c7 100644 --- a/crates/bevy_ecs/macros/src/component.rs +++ b/crates/bevy_ecs/macros/src/component.rs @@ -47,7 +47,7 @@ pub fn derive_resource(input: TokenStream) -> TokenStream { } }); - let storage = storage_path(&bevy_ecs_path, StorageTy::Table); + let storage = storage_path(&bevy_ecs_path, StorageTy::SparseSet); ast.generics .make_where_clause()