Wider ECS Benchmarks (#5123)
# Objective As a part of evaluating #4800, at the behest of @cart, it was noted that the ECS microbenchmarks all focus on singular component queries, whereas in reality most systems will have wider queries with multiple components in each. ## Solution Use const generics to add wider variants of existing benchmarks.
This commit is contained in:
parent
6e50b249a4
commit
ba3d8bedc5
@ -0,0 +1,70 @@
|
||||
use bevy_ecs::prelude::*;
|
||||
|
||||
macro_rules! create_entities {
|
||||
($world:ident; $( $variants:ident ),*) => {
|
||||
$(
|
||||
#[derive(Component)]
|
||||
struct $variants(f32);
|
||||
for _ in 0..20 {
|
||||
$world.spawn().insert_bundle((
|
||||
$variants(0.0),
|
||||
Data::<0>(1.0),
|
||||
Data::<1>(1.0),
|
||||
Data::<2>(1.0),
|
||||
Data::<3>(1.0),
|
||||
Data::<4>(1.0),
|
||||
Data::<5>(1.0),
|
||||
Data::<6>(1.0),
|
||||
Data::<7>(1.0),
|
||||
Data::<8>(1.0),
|
||||
Data::<9>(1.0),
|
||||
Data::<10>(1.0),
|
||||
));
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
struct Data<const X: usize>(f32);
|
||||
|
||||
pub struct Benchmark<'w>(World, QueryState<(
|
||||
&'w mut Data<0>,
|
||||
&'w mut Data<1>,
|
||||
&'w mut Data<2>,
|
||||
&'w mut Data<3>,
|
||||
&'w mut Data<4>,
|
||||
&'w mut Data<5>,
|
||||
&'w mut Data<6>,
|
||||
&'w mut Data<7>,
|
||||
&'w mut Data<8>,
|
||||
&'w mut Data<9>,
|
||||
&'w mut Data<10>,
|
||||
)>);
|
||||
|
||||
impl<'w> Benchmark<'w> {
|
||||
pub fn new() -> Self {
|
||||
let mut world = World::new();
|
||||
|
||||
create_entities!(world; A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z);
|
||||
|
||||
let query = world.query();
|
||||
Self(world, query)
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
self.1.for_each_mut(&mut self.0, |mut data| {
|
||||
data.0.0 *= 2.0;
|
||||
data.1.0 *= 2.0;
|
||||
data.2.0 *= 2.0;
|
||||
data.3.0 *= 2.0;
|
||||
data.4.0 *= 2.0;
|
||||
data.5.0 *= 2.0;
|
||||
data.6.0 *= 2.0;
|
||||
data.7.0 *= 2.0;
|
||||
data.8.0 *= 2.0;
|
||||
data.9.0 *= 2.0;
|
||||
data.10.0 *= 2.0;
|
||||
});
|
||||
}
|
||||
}
|
70
benches/benches/bevy_ecs/ecs_bench_suite/frag_iter_wide.rs
Normal file
70
benches/benches/bevy_ecs/ecs_bench_suite/frag_iter_wide.rs
Normal file
@ -0,0 +1,70 @@
|
||||
use bevy_ecs::prelude::*;
|
||||
|
||||
macro_rules! create_entities {
|
||||
($world:ident; $( $variants:ident ),*) => {
|
||||
$(
|
||||
#[derive(Component)]
|
||||
struct $variants(f32);
|
||||
for _ in 0..20 {
|
||||
$world.spawn().insert_bundle((
|
||||
$variants(0.0),
|
||||
Data::<0>(1.0),
|
||||
Data::<1>(1.0),
|
||||
Data::<2>(1.0),
|
||||
Data::<3>(1.0),
|
||||
Data::<4>(1.0),
|
||||
Data::<5>(1.0),
|
||||
Data::<6>(1.0),
|
||||
Data::<7>(1.0),
|
||||
Data::<8>(1.0),
|
||||
Data::<9>(1.0),
|
||||
Data::<10>(1.0),
|
||||
));
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
struct Data<const X: usize>(f32);
|
||||
|
||||
pub struct Benchmark<'w>(World, QueryState<(
|
||||
&'w mut Data<0>,
|
||||
&'w mut Data<1>,
|
||||
&'w mut Data<2>,
|
||||
&'w mut Data<3>,
|
||||
&'w mut Data<4>,
|
||||
&'w mut Data<5>,
|
||||
&'w mut Data<6>,
|
||||
&'w mut Data<7>,
|
||||
&'w mut Data<8>,
|
||||
&'w mut Data<9>,
|
||||
&'w mut Data<10>,
|
||||
)>);
|
||||
|
||||
impl<'w> Benchmark<'w> {
|
||||
pub fn new() -> Self {
|
||||
let mut world = World::new();
|
||||
|
||||
create_entities!(world; A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z);
|
||||
|
||||
let query = world.query();
|
||||
Self(world, query)
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
for mut data in self.1.iter_mut(&mut self.0) {
|
||||
data.0.0 *= 2.0;
|
||||
data.1.0 *= 2.0;
|
||||
data.2.0 *= 2.0;
|
||||
data.3.0 *= 2.0;
|
||||
data.4.0 *= 2.0;
|
||||
data.5.0 *= 2.0;
|
||||
data.6.0 *= 2.0;
|
||||
data.7.0 *= 2.0;
|
||||
data.8.0 *= 2.0;
|
||||
data.9.0 *= 2.0;
|
||||
data.10.0 *= 2.0;
|
||||
}
|
||||
}
|
||||
}
|
@ -5,7 +5,9 @@ mod add_remove_big_table;
|
||||
mod add_remove_sparse_set;
|
||||
mod add_remove_table;
|
||||
mod frag_iter;
|
||||
mod frag_iter_wide;
|
||||
mod frag_iter_foreach;
|
||||
mod frag_iter_foreach_wide;
|
||||
mod get_component;
|
||||
mod get_component_system;
|
||||
mod heavy_compute;
|
||||
@ -13,12 +15,18 @@ mod schedule;
|
||||
mod simple_insert;
|
||||
mod simple_insert_unbatched;
|
||||
mod simple_iter;
|
||||
mod simple_iter_wide;
|
||||
mod simple_iter_foreach;
|
||||
mod simple_iter_foreach_wide;
|
||||
mod simple_iter_sparse;
|
||||
mod simple_iter_sparse_wide;
|
||||
mod simple_iter_sparse_foreach;
|
||||
mod simple_iter_sparse_foreach_wide;
|
||||
mod simple_iter_system;
|
||||
mod sparse_frag_iter;
|
||||
mod sparse_frag_iter_wide;
|
||||
mod sparse_frag_iter_foreach;
|
||||
mod sparse_frag_iter_foreach_wide;
|
||||
|
||||
fn bench_simple_insert(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("simple_insert");
|
||||
@ -43,6 +51,10 @@ fn bench_simple_iter(c: &mut Criterion) {
|
||||
let mut bench = simple_iter::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("wide", |b| {
|
||||
let mut bench = simple_iter_wide::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("system", |b| {
|
||||
let mut bench = simple_iter_system::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
@ -51,14 +63,26 @@ fn bench_simple_iter(c: &mut Criterion) {
|
||||
let mut bench = simple_iter_sparse::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("sparse_wide", |b| {
|
||||
let mut bench = simple_iter_sparse_wide::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("foreach", |b| {
|
||||
let mut bench = simple_iter_foreach::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("foreach_wide", |b| {
|
||||
let mut bench = simple_iter_foreach_wide::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("sparse_foreach", |b| {
|
||||
let mut bench = simple_iter_sparse_foreach::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("sparse_foreach_wide", |b| {
|
||||
let mut bench = simple_iter_sparse_foreach_wide::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.finish();
|
||||
}
|
||||
|
||||
@ -70,10 +94,18 @@ fn bench_frag_iter_bc(c: &mut Criterion) {
|
||||
let mut bench = frag_iter::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("wide", |b| {
|
||||
let mut bench = frag_iter_wide::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("foreach", |b| {
|
||||
let mut bench = frag_iter_foreach::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("foreach_wide", |b| {
|
||||
let mut bench = frag_iter_foreach_wide::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.finish();
|
||||
}
|
||||
|
||||
@ -85,10 +117,18 @@ fn bench_sparse_frag_iter(c: &mut Criterion) {
|
||||
let mut bench = sparse_frag_iter::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("wide", |b| {
|
||||
let mut bench = sparse_frag_iter_wide::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("foreach", |b| {
|
||||
let mut bench = sparse_frag_iter_foreach::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("foreach_wide", |b| {
|
||||
let mut bench = sparse_frag_iter_foreach_wide::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.finish();
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,63 @@
|
||||
use bevy_ecs::prelude::*;
|
||||
use glam::*;
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Transform(Mat4);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Position<const X: usize>(Vec3);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Rotation(Vec3);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Velocity<const X: usize>(Vec3);
|
||||
|
||||
pub struct Benchmark<'w>(World, QueryState<(
|
||||
&'w Velocity<0>,
|
||||
&'w mut Position<0>,
|
||||
&'w Velocity<1>,
|
||||
&'w mut Position<1>,
|
||||
&'w Velocity<2>,
|
||||
&'w mut Position<2>,
|
||||
&'w Velocity<3>,
|
||||
&'w mut Position<3>,
|
||||
&'w Velocity<4>,
|
||||
&'w mut Position<4>,
|
||||
)>);
|
||||
|
||||
impl<'w> Benchmark<'w> {
|
||||
pub fn new() -> Self {
|
||||
let mut world = World::new();
|
||||
|
||||
// TODO: batch this
|
||||
for _ in 0..10_000 {
|
||||
world.spawn().insert_bundle((
|
||||
Transform(Mat4::from_scale(Vec3::ONE)),
|
||||
Rotation(Vec3::X),
|
||||
Position::<0>(Vec3::X),
|
||||
Velocity::<0>(Vec3::X),
|
||||
Position::<1>(Vec3::X),
|
||||
Velocity::<1>(Vec3::X),
|
||||
Position::<2>(Vec3::X),
|
||||
Velocity::<2>(Vec3::X),
|
||||
Position::<3>(Vec3::X),
|
||||
Velocity::<3>(Vec3::X),
|
||||
Position::<4>(Vec3::X),
|
||||
Velocity::<4>(Vec3::X),
|
||||
));
|
||||
}
|
||||
|
||||
let query = world.query();
|
||||
Self(world, query)
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
self.1.for_each_mut(&mut self.0, |mut item| {
|
||||
item.1.0 += item.0.0;
|
||||
item.3.0 += item.2.0;
|
||||
item.5.0 += item.4.0;
|
||||
item.7.0 += item.6.0;
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
use bevy_ecs::prelude::*;
|
||||
use glam::*;
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Transform(Mat4);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
#[component(storage = "SparseSet")]
|
||||
struct Position<const X: usize>(Vec3);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Rotation(Vec3);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
#[component(storage = "SparseSet")]
|
||||
struct Velocity<const X: usize>(Vec3);
|
||||
|
||||
pub struct Benchmark<'w>(World, QueryState<(
|
||||
&'w Velocity<0>,
|
||||
&'w mut Position<0>,
|
||||
&'w Velocity<1>,
|
||||
&'w mut Position<1>,
|
||||
&'w Velocity<2>,
|
||||
&'w mut Position<2>,
|
||||
&'w Velocity<3>,
|
||||
&'w mut Position<3>,
|
||||
&'w Velocity<4>,
|
||||
&'w mut Position<4>,
|
||||
)>);
|
||||
|
||||
impl<'w> Benchmark<'w> {
|
||||
pub fn new() -> Self {
|
||||
let mut world = World::new();
|
||||
|
||||
// TODO: batch this
|
||||
for _ in 0..10_000 {
|
||||
world.spawn().insert_bundle((
|
||||
Transform(Mat4::from_scale(Vec3::ONE)),
|
||||
Rotation(Vec3::X),
|
||||
Position::<0>(Vec3::X),
|
||||
Velocity::<0>(Vec3::X),
|
||||
Position::<1>(Vec3::X),
|
||||
Velocity::<1>(Vec3::X),
|
||||
Position::<2>(Vec3::X),
|
||||
Velocity::<2>(Vec3::X),
|
||||
Position::<3>(Vec3::X),
|
||||
Velocity::<3>(Vec3::X),
|
||||
Position::<4>(Vec3::X),
|
||||
Velocity::<4>(Vec3::X),
|
||||
));
|
||||
}
|
||||
|
||||
let query = world.query();
|
||||
Self(world, query)
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
self.1.for_each_mut(&mut self.0, |mut item| {
|
||||
item.1.0 += item.0.0;
|
||||
item.3.0 += item.2.0;
|
||||
item.5.0 += item.4.0;
|
||||
item.7.0 += item.6.0;
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
use bevy_ecs::prelude::*;
|
||||
use glam::*;
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Transform(Mat4);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
#[component(storage = "SparseSet")]
|
||||
struct Position<const X: usize>(Vec3);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Rotation(Vec3);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
#[component(storage = "SparseSet")]
|
||||
struct Velocity<const X: usize>(Vec3);
|
||||
|
||||
pub struct Benchmark<'w>(World, QueryState<(
|
||||
&'w Velocity<0>,
|
||||
&'w mut Position<0>,
|
||||
&'w Velocity<1>,
|
||||
&'w mut Position<1>,
|
||||
&'w Velocity<2>,
|
||||
&'w mut Position<2>,
|
||||
&'w Velocity<3>,
|
||||
&'w mut Position<3>,
|
||||
&'w Velocity<4>,
|
||||
&'w mut Position<4>,
|
||||
)>);
|
||||
|
||||
impl<'w> Benchmark<'w> {
|
||||
pub fn new() -> Self {
|
||||
let mut world = World::new();
|
||||
|
||||
// TODO: batch this
|
||||
for _ in 0..10_000 {
|
||||
world.spawn().insert_bundle((
|
||||
Transform(Mat4::from_scale(Vec3::ONE)),
|
||||
Rotation(Vec3::X),
|
||||
Position::<0>(Vec3::X),
|
||||
Velocity::<0>(Vec3::X),
|
||||
Position::<1>(Vec3::X),
|
||||
Velocity::<1>(Vec3::X),
|
||||
Position::<2>(Vec3::X),
|
||||
Velocity::<2>(Vec3::X),
|
||||
Position::<3>(Vec3::X),
|
||||
Velocity::<3>(Vec3::X),
|
||||
Position::<4>(Vec3::X),
|
||||
Velocity::<4>(Vec3::X),
|
||||
));
|
||||
}
|
||||
|
||||
let query = world.query();
|
||||
Self(world, query)
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
for mut item in self.1.iter_mut(&mut self.0) {
|
||||
item.1.0 += item.0.0;
|
||||
item.3.0 += item.2.0;
|
||||
item.5.0 += item.4.0;
|
||||
item.7.0 += item.6.0;
|
||||
}
|
||||
}
|
||||
}
|
63
benches/benches/bevy_ecs/ecs_bench_suite/simple_iter_wide.rs
Normal file
63
benches/benches/bevy_ecs/ecs_bench_suite/simple_iter_wide.rs
Normal file
@ -0,0 +1,63 @@
|
||||
use bevy_ecs::prelude::*;
|
||||
use glam::*;
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Transform(Mat4);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Position<const X: usize>(Vec3);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Rotation(Vec3);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Velocity<const X: usize>(Vec3);
|
||||
|
||||
pub struct Benchmark<'w>(World, QueryState<(
|
||||
&'w Velocity<0>,
|
||||
&'w mut Position<0>,
|
||||
&'w Velocity<1>,
|
||||
&'w mut Position<1>,
|
||||
&'w Velocity<2>,
|
||||
&'w mut Position<2>,
|
||||
&'w Velocity<3>,
|
||||
&'w mut Position<3>,
|
||||
&'w Velocity<4>,
|
||||
&'w mut Position<4>,
|
||||
)>);
|
||||
|
||||
impl<'w> Benchmark<'w> {
|
||||
pub fn new() -> Self {
|
||||
let mut world = World::new();
|
||||
|
||||
// TODO: batch this
|
||||
for _ in 0..10_000 {
|
||||
world.spawn().insert_bundle((
|
||||
Transform(Mat4::from_scale(Vec3::ONE)),
|
||||
Rotation(Vec3::X),
|
||||
Position::<0>(Vec3::X),
|
||||
Velocity::<0>(Vec3::X),
|
||||
Position::<1>(Vec3::X),
|
||||
Velocity::<1>(Vec3::X),
|
||||
Position::<2>(Vec3::X),
|
||||
Velocity::<2>(Vec3::X),
|
||||
Position::<3>(Vec3::X),
|
||||
Velocity::<3>(Vec3::X),
|
||||
Position::<4>(Vec3::X),
|
||||
Velocity::<4>(Vec3::X),
|
||||
));
|
||||
}
|
||||
|
||||
let query = world.query();
|
||||
Self(world, query)
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
for mut item in self.1.iter_mut(&mut self.0) {
|
||||
item.1.0 += item.0.0;
|
||||
item.3.0 += item.2.0;
|
||||
item.5.0 += item.4.0;
|
||||
item.7.0 += item.6.0;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
use bevy_ecs::prelude::*;
|
||||
|
||||
macro_rules! create_entities {
|
||||
($world:ident; $( $variants:ident ),*) => {
|
||||
$(
|
||||
#[derive(Component)]
|
||||
struct $variants(f32);
|
||||
for _ in 0..5 {
|
||||
$world.spawn().insert($variants(0.0));
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
struct Data<const X: usize>(f32);
|
||||
|
||||
pub struct Benchmark<'w>(World, QueryState<(
|
||||
&'w mut Data<0>,
|
||||
&'w mut Data<1>,
|
||||
&'w mut Data<2>,
|
||||
&'w mut Data<3>,
|
||||
&'w mut Data<4>,
|
||||
&'w mut Data<5>,
|
||||
&'w mut Data<6>,
|
||||
&'w mut Data<7>,
|
||||
&'w mut Data<8>,
|
||||
&'w mut Data<9>,
|
||||
&'w mut Data<10>,
|
||||
)>);
|
||||
|
||||
impl<'w> Benchmark<'w> {
|
||||
pub fn new() -> Self {
|
||||
let mut world = World::new();
|
||||
for _ in 0..5 {
|
||||
world.spawn().insert_bundle((
|
||||
Data::<0>(1.0),
|
||||
Data::<1>(1.0),
|
||||
Data::<2>(1.0),
|
||||
Data::<3>(1.0),
|
||||
Data::<4>(1.0),
|
||||
Data::<5>(1.0),
|
||||
Data::<6>(1.0),
|
||||
Data::<7>(1.0),
|
||||
Data::<8>(1.0),
|
||||
Data::<9>(1.0),
|
||||
Data::<10>(1.0),
|
||||
));
|
||||
}
|
||||
|
||||
create_entities!(world; C00, C01, C02, C03, C04, C05, C06, C07, C08, C09);
|
||||
create_entities!(world; C10, C11, C12, C13, C14, C15, C16, C17, C18, C19);
|
||||
create_entities!(world; C20, C21, C22, C23, C24, C25, C26, C27, C28, C29);
|
||||
create_entities!(world; C30, C31, C32, C33, C34, C35, C36, C37, C38, C39);
|
||||
create_entities!(world; C40, C41, C42, C43, C44, C45, C46, C47, C48, C49);
|
||||
create_entities!(world; C50, C51, C52, C53, C54, C55, C56, C57, C58, C59);
|
||||
create_entities!(world; C60, C61, C62, C63, C64, C65, C66, C67, C68, C69);
|
||||
create_entities!(world; C70, C71, C72, C73, C74, C75, C76, C77, C78, C79);
|
||||
create_entities!(world; C80, C81, C82, C83, C84, C85, C86, C87, C88, C89);
|
||||
create_entities!(world; C90, C91, C92, C93, C94, C95, C96, C97, C98, C99);
|
||||
let query = world.query();
|
||||
Self(world, query)
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
self.1.for_each_mut(&mut self.0, |mut data| {
|
||||
data.0.0 *= 2.0;
|
||||
data.1.0 *= 2.0;
|
||||
data.2.0 *= 2.0;
|
||||
data.3.0 *= 2.0;
|
||||
data.4.0 *= 2.0;
|
||||
data.5.0 *= 2.0;
|
||||
data.6.0 *= 2.0;
|
||||
data.7.0 *= 2.0;
|
||||
data.8.0 *= 2.0;
|
||||
data.9.0 *= 2.0;
|
||||
data.10.0 *= 2.0;
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
use bevy_ecs::prelude::*;
|
||||
|
||||
macro_rules! create_entities {
|
||||
($world:ident; $( $variants:ident ),*) => {
|
||||
$(
|
||||
#[derive(Component)]
|
||||
struct $variants(f32);
|
||||
for _ in 0..5 {
|
||||
$world.spawn().insert($variants(0.0));
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
#[derive(Component)]
|
||||
struct Data<const X: usize>(f32);
|
||||
|
||||
pub struct Benchmark<'w>(World, QueryState<(
|
||||
&'w mut Data<0>,
|
||||
&'w mut Data<1>,
|
||||
&'w mut Data<2>,
|
||||
&'w mut Data<3>,
|
||||
&'w mut Data<4>,
|
||||
&'w mut Data<5>,
|
||||
&'w mut Data<6>,
|
||||
&'w mut Data<7>,
|
||||
&'w mut Data<8>,
|
||||
&'w mut Data<9>,
|
||||
&'w mut Data<10>,
|
||||
)>);
|
||||
|
||||
impl<'w> Benchmark<'w> {
|
||||
pub fn new() -> Self {
|
||||
let mut world = World::new();
|
||||
|
||||
for _ in 0..5 {
|
||||
world.spawn().insert_bundle((
|
||||
Data::<0>(1.0),
|
||||
Data::<1>(1.0),
|
||||
Data::<2>(1.0),
|
||||
Data::<3>(1.0),
|
||||
Data::<4>(1.0),
|
||||
Data::<5>(1.0),
|
||||
Data::<6>(1.0),
|
||||
Data::<7>(1.0),
|
||||
Data::<8>(1.0),
|
||||
Data::<9>(1.0),
|
||||
Data::<10>(1.0),
|
||||
));
|
||||
}
|
||||
|
||||
create_entities!(world; C00, C01, C02, C03, C04, C05, C06, C07, C08, C09);
|
||||
create_entities!(world; C10, C11, C12, C13, C14, C15, C16, C17, C18, C19);
|
||||
create_entities!(world; C20, C21, C22, C23, C24, C25, C26, C27, C28, C29);
|
||||
create_entities!(world; C30, C31, C32, C33, C34, C35, C36, C37, C38, C39);
|
||||
create_entities!(world; C40, C41, C42, C43, C44, C45, C46, C47, C48, C49);
|
||||
create_entities!(world; C50, C51, C52, C53, C54, C55, C56, C57, C58, C59);
|
||||
create_entities!(world; C60, C61, C62, C63, C64, C65, C66, C67, C68, C69);
|
||||
create_entities!(world; C70, C71, C72, C73, C74, C75, C76, C77, C78, C79);
|
||||
create_entities!(world; C80, C81, C82, C83, C84, C85, C86, C87, C88, C89);
|
||||
create_entities!(world; C90, C91, C92, C93, C94, C95, C96, C97, C98, C99);
|
||||
let query = world.query();
|
||||
Self(world, query)
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
for mut data in self.1.iter_mut(&mut self.0) {
|
||||
data.0.0 *= 2.0;
|
||||
data.1.0 *= 2.0;
|
||||
data.2.0 *= 2.0;
|
||||
data.3.0 *= 2.0;
|
||||
data.4.0 *= 2.0;
|
||||
data.5.0 *= 2.0;
|
||||
data.6.0 *= 2.0;
|
||||
data.7.0 *= 2.0;
|
||||
data.8.0 *= 2.0;
|
||||
data.9.0 *= 2.0;
|
||||
data.10.0 *= 2.0;
|
||||
}
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@ use bevy_ecs::{
|
||||
component::Component,
|
||||
entity::Entity,
|
||||
system::{Query, SystemState},
|
||||
bundle::Bundle,
|
||||
world::World,
|
||||
};
|
||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||
@ -26,6 +27,12 @@ struct Table(f32);
|
||||
#[derive(Component, Default)]
|
||||
#[component(storage = "SparseSet")]
|
||||
struct Sparse(f32);
|
||||
#[derive(Component, Default)]
|
||||
#[component(storage = "Table")]
|
||||
struct WideTable<const X: usize>(f32);
|
||||
#[derive(Component, Default)]
|
||||
#[component(storage = "SparseSet")]
|
||||
struct WideSparse<const X: usize>(f32);
|
||||
|
||||
const RANGE: std::ops::Range<u32> = 5..6;
|
||||
|
||||
@ -39,6 +46,12 @@ fn setup<T: Component + Default>(entity_count: u32) -> World {
|
||||
black_box(world)
|
||||
}
|
||||
|
||||
fn setup_wide<T: Bundle + Default>(entity_count: u32) -> World {
|
||||
let mut world = World::default();
|
||||
world.spawn_batch((0..entity_count).map(|_| T::default()));
|
||||
black_box(world)
|
||||
}
|
||||
|
||||
fn world_entity(criterion: &mut Criterion) {
|
||||
let mut group = criterion.benchmark_group("world_entity");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
@ -108,10 +121,60 @@ fn world_query_get(criterion: &mut Criterion) {
|
||||
}
|
||||
});
|
||||
});
|
||||
group.bench_function(format!("{}_entities_table_wide", entity_count), |bencher| {
|
||||
let mut world = setup_wide::<(
|
||||
WideTable<0>,
|
||||
WideTable<1>,
|
||||
WideTable<2>,
|
||||
WideTable<3>,
|
||||
WideTable<4>,
|
||||
WideTable<5>,
|
||||
)>(entity_count);
|
||||
let mut query = world.query::<(
|
||||
&WideTable<0>,
|
||||
&WideTable<1>,
|
||||
&WideTable<2>,
|
||||
&WideTable<3>,
|
||||
&WideTable<4>,
|
||||
&WideTable<5>,
|
||||
)>();
|
||||
|
||||
bencher.iter(|| {
|
||||
for i in 0..entity_count {
|
||||
let entity = Entity::from_raw(i);
|
||||
assert!(query.get(&world, entity).is_ok());
|
||||
}
|
||||
});
|
||||
});
|
||||
group.bench_function(format!("{}_entities_sparse", entity_count), |bencher| {
|
||||
let mut world = setup::<Sparse>(entity_count);
|
||||
let mut query = world.query::<&Sparse>();
|
||||
|
||||
bencher.iter(|| {
|
||||
for i in 0..entity_count {
|
||||
let entity = Entity::from_raw(i);
|
||||
assert!(query.get(&world, entity).is_ok());
|
||||
}
|
||||
});
|
||||
});
|
||||
group.bench_function(format!("{}_entities_sparse_wide", entity_count), |bencher| {
|
||||
let mut world = setup_wide::<(
|
||||
WideSparse<0>,
|
||||
WideSparse<1>,
|
||||
WideSparse<2>,
|
||||
WideSparse<3>,
|
||||
WideSparse<4>,
|
||||
WideSparse<5>,
|
||||
)>(entity_count);
|
||||
let mut query = world.query::<(
|
||||
&WideSparse<0>,
|
||||
&WideSparse<1>,
|
||||
&WideSparse<2>,
|
||||
&WideSparse<3>,
|
||||
&WideSparse<4>,
|
||||
&WideSparse<5>,
|
||||
)>();
|
||||
|
||||
bencher.iter(|| {
|
||||
for i in 0..entity_count {
|
||||
let entity = Entity::from_raw(i);
|
||||
|
Loading…
Reference in New Issue
Block a user