mirror of
https://github.com/bevyengine/bevy.git
synced 2026-05-06 06:06:42 -04:00
Store resources on sparse sets (#24077)
# Objective Part of the #23988 and #24058 saga. We attempt to speed up resource access. ## Solution When messing around with #23988 I noticed that changing the storage type mattered a lot for the benchmarks. ## Testing Added benchmarks from #24058 and got the following micro benchmarks compared to main: ``` ecs::resources::get time: [6.3584 ns 6.3840 ns 6.4097 ns] change: [−10.625% −10.075% −9.6652%] (p = 0.00 < 0.05) Performance has improved. Found 9 outliers among 100 measurements (9.00%) 1 (1.00%) low mild 8 (8.00%) high mild ecs::resources::get_mut time: [7.4181 ns 7.4343 ns 7.4515 ns] change: [−39.895% −39.304% −38.809%] (p = 0.00 < 0.05) Performance has improved. Found 7 outliers among 100 measurements (7.00%) 5 (5.00%) high mild 2 (2.00%) high severe ecs::resources::insert_remove time: [89.515 ns 89.654 ns 89.815 ns] change: [−20.163% −16.527% −11.930%] (p = 0.00 < 0.05) Performance has improved. Found 10 outliers among 100 measurements (10.00%) 2 (2.00%) low severe 1 (1.00%) low mild 3 (3.00%) high mild 4 (4.00%) high severe ``` If someone wants to double-check these numbers, I encourage you to do so.
This commit is contained in:
committed by
Carter Anderson
parent
0d6131008c
commit
a50b65dfa5
@@ -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,
|
||||
|
||||
@@ -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::<R>());
|
||||
});
|
||||
}
|
||||
|
||||
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::<R>());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
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::<R>()
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
use bevy_ecs_macro_logic::component::DeriveComponent;
|
||||
use bevy_ecs_macro_logic::component::{DeriveComponent, StorageTy};
|
||||
use bevy_macro_utils::fq_std::FQOption;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
@@ -10,6 +10,7 @@ pub fn derive_resource(ast: &mut DeriveInput) -> TokenStream {
|
||||
Ok(value) => value,
|
||||
Err(e) => return e.into_compile_error(),
|
||||
};
|
||||
derive_component.storage = StorageTy::SparseSet;
|
||||
|
||||
let struct_name = &ast.ident;
|
||||
let (_, type_generics, _) = &ast.generics.split_for_impl();
|
||||
|
||||
Reference in New Issue
Block a user