mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
ECS benchmarks organization (#5189)
## Objective Fixes: #5110 ## Solution - Moved benches into separate modules according to the part of ECS they are testing. - Made so all ECS benches are included in one `benches.rs` so they don’t need to be added separately in `Cargo.toml`. - Renamed a bunch of files to have more coherent names. - Merged `schedule.rs` and `system_schedule.rs` into one file.
This commit is contained in:
parent
050251da5a
commit
179f719553
41 changed files with 612 additions and 639 deletions
|
@ -18,38 +18,8 @@ bevy_tasks = { path = "../crates/bevy_tasks" }
|
|||
bevy_utils = { path = "../crates/bevy_utils" }
|
||||
|
||||
[[bench]]
|
||||
name = "archetype_updates"
|
||||
path = "benches/bevy_ecs/archetype_updates.rs"
|
||||
harness = false
|
||||
|
||||
[[bench]]
|
||||
name = "ecs_bench_suite"
|
||||
path = "benches/bevy_ecs/ecs_bench_suite/mod.rs"
|
||||
harness = false
|
||||
|
||||
[[bench]]
|
||||
name = "run_criteria"
|
||||
path = "benches/bevy_ecs/run_criteria.rs"
|
||||
harness = false
|
||||
|
||||
[[bench]]
|
||||
name = "commands"
|
||||
path = "benches/bevy_ecs/commands.rs"
|
||||
harness = false
|
||||
|
||||
[[bench]]
|
||||
name = "system_stage"
|
||||
path = "benches/bevy_ecs/stages.rs"
|
||||
harness = false
|
||||
|
||||
[[bench]]
|
||||
name = "world_get"
|
||||
path = "benches/bevy_ecs/world_get.rs"
|
||||
harness = false
|
||||
|
||||
[[bench]]
|
||||
name = "schedule"
|
||||
path = "benches/bevy_ecs/schedule.rs"
|
||||
name = "ecs"
|
||||
path = "benches/bevy_ecs/benches.rs"
|
||||
harness = false
|
||||
|
||||
[[bench]]
|
||||
|
|
13
benches/benches/bevy_ecs/benches.rs
Normal file
13
benches/benches/bevy_ecs/benches.rs
Normal file
|
@ -0,0 +1,13 @@
|
|||
use criterion::criterion_main;
|
||||
|
||||
mod components;
|
||||
mod iteration;
|
||||
mod scheduling;
|
||||
mod world;
|
||||
|
||||
criterion_main!(
|
||||
iteration::iterations_benches,
|
||||
components::components_benches,
|
||||
scheduling::scheduling_benches,
|
||||
world::world_benches,
|
||||
);
|
|
@ -3,10 +3,7 @@ use bevy_ecs::{
|
|||
schedule::{Stage, SystemStage},
|
||||
world::World,
|
||||
};
|
||||
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
|
||||
|
||||
criterion_group!(benches, no_archetypes, added_archetypes);
|
||||
criterion_main!(benches);
|
||||
use criterion::{BenchmarkId, Criterion};
|
||||
|
||||
#[derive(Component)]
|
||||
struct A<const N: u16>(f32);
|
||||
|
@ -77,7 +74,7 @@ fn add_archetypes(world: &mut World, count: u16) {
|
|||
}
|
||||
}
|
||||
|
||||
fn no_archetypes(criterion: &mut Criterion) {
|
||||
pub fn no_archetypes(criterion: &mut Criterion) {
|
||||
let mut group = criterion.benchmark_group("no_archetypes");
|
||||
for i in 0..=5 {
|
||||
let system_count = i * 20;
|
||||
|
@ -94,7 +91,7 @@ fn no_archetypes(criterion: &mut Criterion) {
|
|||
}
|
||||
}
|
||||
|
||||
fn added_archetypes(criterion: &mut Criterion) {
|
||||
pub fn added_archetypes(criterion: &mut Criterion) {
|
||||
const SYSTEM_COUNT: usize = 100;
|
||||
let mut group = criterion.benchmark_group("added_archetypes");
|
||||
for archetype_count in [100, 200, 500, 1000, 2000, 5000, 10000] {
|
65
benches/benches/bevy_ecs/components/mod.rs
Normal file
65
benches/benches/bevy_ecs/components/mod.rs
Normal file
|
@ -0,0 +1,65 @@
|
|||
use criterion::*;
|
||||
|
||||
mod add_remove_big_sparse_set;
|
||||
mod add_remove_big_table;
|
||||
mod add_remove_sparse_set;
|
||||
mod add_remove_table;
|
||||
mod archetype_updates;
|
||||
mod insert_simple;
|
||||
mod insert_simple_unbatched;
|
||||
|
||||
use archetype_updates::*;
|
||||
|
||||
criterion_group!(
|
||||
components_benches,
|
||||
add_remove,
|
||||
add_remove_big,
|
||||
insert_simple,
|
||||
no_archetypes,
|
||||
added_archetypes,
|
||||
);
|
||||
|
||||
fn add_remove(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("add_remove");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(4));
|
||||
group.bench_function("table", |b| {
|
||||
let mut bench = add_remove_table::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("sparse_set", |b| {
|
||||
let mut bench = add_remove_sparse_set::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.finish();
|
||||
}
|
||||
|
||||
fn add_remove_big(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("add_remove_big");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(4));
|
||||
group.bench_function("table", |b| {
|
||||
let mut bench = add_remove_big_table::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("sparse_set", |b| {
|
||||
let mut bench = add_remove_big_sparse_set::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.finish();
|
||||
}
|
||||
|
||||
fn insert_simple(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("insert_simple");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(4));
|
||||
group.bench_function("base", |b| {
|
||||
let mut bench = insert_simple::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("unbatched", |b| {
|
||||
let mut bench = insert_simple_unbatched::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.finish();
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
use bevy_ecs::prelude::*;
|
||||
|
||||
#[derive(Component)]
|
||||
struct A(f32);
|
||||
|
||||
pub struct Benchmark<'w>(World, Entity, QueryState<&'w mut A>);
|
||||
|
||||
impl<'w> Benchmark<'w> {
|
||||
pub fn new() -> Self {
|
||||
let mut world = World::new();
|
||||
|
||||
let entity = world.spawn().insert(A(0.0)).id();
|
||||
let query = world.query::<&mut A>();
|
||||
Self(world, entity, query)
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
for _x in 0..100000 {
|
||||
let mut a = unsafe { self.2.get_unchecked(&mut self.0, self.1).unwrap() };
|
||||
a.0 += 1.0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
use bevy_ecs::prelude::*;
|
||||
|
||||
#[derive(Component)]
|
||||
struct A(f32);
|
||||
|
||||
pub struct Benchmark(World, Entity, Box<dyn System<In = Entity, Out = ()>>);
|
||||
|
||||
impl Benchmark {
|
||||
pub fn new() -> Self {
|
||||
let mut world = World::new();
|
||||
|
||||
let entity = world.spawn().insert(A(0.0)).id();
|
||||
fn query_system(In(entity): In<Entity>, mut query: Query<&mut A>) {
|
||||
for _ in 0..100_000 {
|
||||
let mut a = query.get_mut(entity).unwrap();
|
||||
a.0 += 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
let mut system = IntoSystem::into_system(query_system);
|
||||
system.initialize(&mut world);
|
||||
system.update_archetype_component_access(&world);
|
||||
Self(world, entity, Box::new(system))
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
self.2.run(self.1, &mut self.0);
|
||||
}
|
||||
}
|
|
@ -1,214 +0,0 @@
|
|||
use criterion::*;
|
||||
|
||||
mod add_remove_big_sparse_set;
|
||||
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;
|
||||
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");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(4));
|
||||
group.bench_function("base", |b| {
|
||||
let mut bench = simple_insert::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("unbatched", |b| {
|
||||
let mut bench = simple_insert_unbatched::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.finish();
|
||||
}
|
||||
|
||||
fn bench_simple_iter(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("simple_iter");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(4));
|
||||
group.bench_function("base", |b| {
|
||||
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());
|
||||
});
|
||||
group.bench_function("sparse", |b| {
|
||||
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();
|
||||
}
|
||||
|
||||
fn bench_frag_iter_bc(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("fragmented_iter");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(4));
|
||||
group.bench_function("base", |b| {
|
||||
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();
|
||||
}
|
||||
|
||||
fn bench_sparse_frag_iter(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("sparse_fragmented_iter");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(4));
|
||||
group.bench_function("base", |b| {
|
||||
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();
|
||||
}
|
||||
|
||||
fn bench_schedule(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("schedule");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(4));
|
||||
group.bench_function("base", |b| {
|
||||
let mut bench = schedule::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.finish();
|
||||
}
|
||||
|
||||
fn bench_heavy_compute(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("heavy_compute");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(4));
|
||||
group.bench_function("base", |b| {
|
||||
let mut bench = heavy_compute::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.finish();
|
||||
}
|
||||
|
||||
fn bench_add_remove(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("add_remove_component");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(4));
|
||||
group.bench_function("table", |b| {
|
||||
let mut bench = add_remove_table::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("sparse_set", |b| {
|
||||
let mut bench = add_remove_sparse_set::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.finish();
|
||||
}
|
||||
|
||||
fn bench_add_remove_big(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("add_remove_component_big");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(4));
|
||||
group.bench_function("table", |b| {
|
||||
let mut bench = add_remove_big_table::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("sparse_set", |b| {
|
||||
let mut bench = add_remove_big_sparse_set::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.finish();
|
||||
}
|
||||
|
||||
fn bench_get_component(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("get_component");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(4));
|
||||
group.bench_function("base", |b| {
|
||||
let mut bench = get_component::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("system", |b| {
|
||||
let mut bench = get_component_system::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.finish();
|
||||
}
|
||||
|
||||
criterion_group!(
|
||||
benchmarks,
|
||||
bench_simple_insert,
|
||||
bench_simple_iter,
|
||||
bench_frag_iter_bc,
|
||||
bench_sparse_frag_iter,
|
||||
bench_schedule,
|
||||
bench_heavy_compute,
|
||||
bench_add_remove,
|
||||
bench_add_remove_big,
|
||||
bench_get_component,
|
||||
);
|
||||
criterion_main!(benchmarks);
|
|
@ -1,58 +0,0 @@
|
|||
use bevy_ecs::prelude::*;
|
||||
|
||||
#[derive(Component)]
|
||||
struct A(f32);
|
||||
#[derive(Component)]
|
||||
struct B(f32);
|
||||
#[derive(Component)]
|
||||
struct C(f32);
|
||||
#[derive(Component)]
|
||||
struct D(f32);
|
||||
#[derive(Component)]
|
||||
struct E(f32);
|
||||
|
||||
fn ab(mut query: Query<(&mut A, &mut B)>) {
|
||||
query.for_each_mut(|(mut a, mut b)| {
|
||||
std::mem::swap(&mut a.0, &mut b.0);
|
||||
});
|
||||
}
|
||||
|
||||
fn cd(mut query: Query<(&mut C, &mut D)>) {
|
||||
query.for_each_mut(|(mut c, mut d)| {
|
||||
std::mem::swap(&mut c.0, &mut d.0);
|
||||
});
|
||||
}
|
||||
|
||||
fn ce(mut query: Query<(&mut C, &mut E)>) {
|
||||
query.for_each_mut(|(mut c, mut e)| {
|
||||
std::mem::swap(&mut c.0, &mut e.0);
|
||||
});
|
||||
}
|
||||
|
||||
pub struct Benchmark(World, SystemStage);
|
||||
|
||||
impl Benchmark {
|
||||
pub fn new() -> Self {
|
||||
let mut world = World::default();
|
||||
|
||||
world.spawn_batch((0..10000).map(|_| (A(0.0), B(0.0))));
|
||||
|
||||
world.spawn_batch((0..10000).map(|_| (A(0.0), B(0.0), C(0.0))));
|
||||
|
||||
world.spawn_batch((0..10000).map(|_| (A(0.0), B(0.0), C(0.0), D(0.0))));
|
||||
|
||||
world.spawn_batch((0..10000).map(|_| (A(0.0), B(0.0), C(0.0), E(0.0))));
|
||||
|
||||
let mut stage = SystemStage::parallel();
|
||||
stage.add_system(ab);
|
||||
stage.add_system(cd);
|
||||
stage.add_system(ce);
|
||||
stage.run(&mut world);
|
||||
|
||||
Self(world, stage)
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
self.1.run(&mut self.0);
|
||||
}
|
||||
}
|
|
@ -1,23 +1,25 @@
|
|||
use bevy_ecs::prelude::*;
|
||||
use bevy_tasks::{ComputeTaskPool, TaskPool};
|
||||
use criterion::Criterion;
|
||||
use glam::*;
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Position(Vec3);
|
||||
pub fn heavy_compute(c: &mut Criterion) {
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Position(Vec3);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Rotation(Vec3);
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Rotation(Vec3);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Velocity(Vec3);
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Velocity(Vec3);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Transform(Mat4);
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Transform(Mat4);
|
||||
|
||||
pub struct Benchmark(World, Box<dyn System<In = (), Out = ()>>);
|
||||
|
||||
impl Benchmark {
|
||||
pub fn new() -> Self {
|
||||
let mut group = c.benchmark_group("heavy_compute");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(4));
|
||||
group.bench_function("base", |b| {
|
||||
ComputeTaskPool::init(TaskPool::default);
|
||||
|
||||
let mut world = World::default();
|
||||
|
@ -45,10 +47,7 @@ impl Benchmark {
|
|||
system.initialize(&mut world);
|
||||
system.update_archetype_component_access(&world);
|
||||
|
||||
Self(world, Box::new(system))
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
self.1.run((), &mut self.0);
|
||||
}
|
||||
b.iter(move || system.run((), &mut world));
|
||||
});
|
||||
group.finish();
|
||||
}
|
|
@ -7,7 +7,7 @@ macro_rules! create_entities {
|
|||
struct $variants(f32);
|
||||
for _ in 0..20 {
|
||||
$world.spawn().insert_bundle((
|
||||
$variants(0.0),
|
||||
$variants(0.0),
|
||||
Data::<0>(1.0),
|
||||
Data::<1>(1.0),
|
||||
Data::<2>(1.0),
|
||||
|
@ -28,19 +28,22 @@ macro_rules! create_entities {
|
|||
#[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>,
|
||||
)>);
|
||||
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 {
|
||||
|
@ -54,17 +57,17 @@ impl<'w> Benchmark<'w> {
|
|||
|
||||
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;
|
||||
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;
|
||||
});
|
||||
}
|
||||
}
|
|
@ -15,19 +15,22 @@ macro_rules! create_entities {
|
|||
#[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>,
|
||||
)>);
|
||||
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 {
|
||||
|
@ -64,17 +67,17 @@ impl<'w> Benchmark<'w> {
|
|||
|
||||
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;
|
||||
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;
|
||||
});
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@ macro_rules! create_entities {
|
|||
struct $variants(f32);
|
||||
for _ in 0..20 {
|
||||
$world.spawn().insert_bundle((
|
||||
$variants(0.0),
|
||||
$variants(0.0),
|
||||
Data::<0>(1.0),
|
||||
Data::<1>(1.0),
|
||||
Data::<2>(1.0),
|
||||
|
@ -28,19 +28,22 @@ macro_rules! create_entities {
|
|||
#[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>,
|
||||
)>);
|
||||
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 {
|
||||
|
@ -54,17 +57,17 @@ impl<'w> Benchmark<'w> {
|
|||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,19 +14,22 @@ macro_rules! create_entities {
|
|||
#[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>,
|
||||
)>);
|
||||
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 {
|
||||
|
@ -64,17 +67,17 @@ impl<'w> Benchmark<'w> {
|
|||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,18 +13,21 @@ 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>,
|
||||
)>);
|
||||
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 {
|
||||
|
@ -54,10 +57,10 @@ impl<'w> Benchmark<'w> {
|
|||
|
||||
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;
|
||||
item.1 .0 += item.0 .0;
|
||||
item.3 .0 += item.2 .0;
|
||||
item.5 .0 += item.4 .0;
|
||||
item.7 .0 += item.6 .0;
|
||||
});
|
||||
}
|
||||
}
|
|
@ -15,18 +15,21 @@ struct Rotation(Vec3);
|
|||
#[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>,
|
||||
)>);
|
||||
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 {
|
||||
|
@ -56,10 +59,10 @@ impl<'w> Benchmark<'w> {
|
|||
|
||||
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;
|
||||
item.1 .0 += item.0 .0;
|
||||
item.3 .0 += item.2 .0;
|
||||
item.5 .0 += item.4 .0;
|
||||
item.7 .0 += item.6 .0;
|
||||
});
|
||||
}
|
||||
}
|
|
@ -13,18 +13,21 @@ 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>,
|
||||
)>);
|
||||
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 {
|
||||
|
@ -54,10 +57,10 @@ impl<'w> Benchmark<'w> {
|
|||
|
||||
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;
|
||||
item.1 .0 += item.0 .0;
|
||||
item.3 .0 += item.2 .0;
|
||||
item.5 .0 += item.4 .0;
|
||||
item.7 .0 += item.6 .0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,18 +15,21 @@ struct Rotation(Vec3);
|
|||
#[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>,
|
||||
)>);
|
||||
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 {
|
||||
|
@ -56,10 +59,10 @@ impl<'w> Benchmark<'w> {
|
|||
|
||||
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;
|
||||
item.1 .0 += item.0 .0;
|
||||
item.3 .0 += item.2 .0;
|
||||
item.5 .0 += item.4 .0;
|
||||
item.7 .0 += item.6 .0;
|
||||
}
|
||||
}
|
||||
}
|
119
benches/benches/bevy_ecs/iteration/mod.rs
Normal file
119
benches/benches/bevy_ecs/iteration/mod.rs
Normal file
|
@ -0,0 +1,119 @@
|
|||
use criterion::*;
|
||||
|
||||
mod heavy_compute;
|
||||
mod iter_frag;
|
||||
mod iter_frag_foreach;
|
||||
mod iter_frag_foreach_sparse;
|
||||
mod iter_frag_foreach_wide;
|
||||
mod iter_frag_foreach_wide_sparse;
|
||||
mod iter_frag_sparse;
|
||||
mod iter_frag_wide;
|
||||
mod iter_frag_wide_sparse;
|
||||
mod iter_simple;
|
||||
mod iter_simple_foreach;
|
||||
mod iter_simple_foreach_sparse_set;
|
||||
mod iter_simple_foreach_wide;
|
||||
mod iter_simple_foreach_wide_sparse_set;
|
||||
mod iter_simple_sparse_set;
|
||||
mod iter_simple_system;
|
||||
mod iter_simple_wide;
|
||||
mod iter_simple_wide_sparse_set;
|
||||
|
||||
use heavy_compute::*;
|
||||
|
||||
criterion_group!(
|
||||
iterations_benches,
|
||||
iter_frag,
|
||||
iter_frag_sparse,
|
||||
iter_simple,
|
||||
heavy_compute,
|
||||
);
|
||||
|
||||
fn iter_simple(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("iter_simple");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(4));
|
||||
group.bench_function("base", |b| {
|
||||
let mut bench = iter_simple::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("wide", |b| {
|
||||
let mut bench = iter_simple_wide::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("system", |b| {
|
||||
let mut bench = iter_simple_system::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("sparse_set", |b| {
|
||||
let mut bench = iter_simple_sparse_set::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("wide_sparse_set", |b| {
|
||||
let mut bench = iter_simple_wide_sparse_set::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("foreach", |b| {
|
||||
let mut bench = iter_simple_foreach::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("foreach_wide", |b| {
|
||||
let mut bench = iter_simple_foreach_wide::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("foreach_sparse_set", |b| {
|
||||
let mut bench = iter_simple_foreach_sparse_set::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("foreach_wide_sparse_set", |b| {
|
||||
let mut bench = iter_simple_foreach_wide_sparse_set::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.finish();
|
||||
}
|
||||
|
||||
fn iter_frag(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("iter_fragmented");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(4));
|
||||
group.bench_function("base", |b| {
|
||||
let mut bench = iter_frag::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("wide", |b| {
|
||||
let mut bench = iter_frag_wide::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("foreach", |b| {
|
||||
let mut bench = iter_frag_foreach::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("foreach_wide", |b| {
|
||||
let mut bench = iter_frag_foreach_wide::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.finish();
|
||||
}
|
||||
|
||||
fn iter_frag_sparse(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("iter_fragmented_sparse");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(4));
|
||||
group.bench_function("base", |b| {
|
||||
let mut bench = iter_frag_sparse::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("wide", |b| {
|
||||
let mut bench = iter_frag_wide_sparse::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("foreach", |b| {
|
||||
let mut bench = iter_frag_foreach_sparse::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.bench_function("foreach_wide", |b| {
|
||||
let mut bench = iter_frag_foreach_wide_sparse::Benchmark::new();
|
||||
b.iter(move || bench.run());
|
||||
});
|
||||
group.finish();
|
||||
}
|
24
benches/benches/bevy_ecs/scheduling/mod.rs
Normal file
24
benches/benches/bevy_ecs/scheduling/mod.rs
Normal file
|
@ -0,0 +1,24 @@
|
|||
use criterion::criterion_group;
|
||||
|
||||
mod run_criteria;
|
||||
mod schedule;
|
||||
mod stages;
|
||||
|
||||
use run_criteria::*;
|
||||
use schedule::*;
|
||||
use stages::*;
|
||||
|
||||
criterion_group!(
|
||||
scheduling_benches,
|
||||
run_criteria_yes,
|
||||
run_criteria_no,
|
||||
run_criteria_yes_with_labels,
|
||||
run_criteria_no_with_labels,
|
||||
run_criteria_yes_with_query,
|
||||
run_criteria_yes_with_resource,
|
||||
empty_systems,
|
||||
busy_systems,
|
||||
contrived,
|
||||
schedule,
|
||||
build_schedule,
|
||||
);
|
|
@ -5,24 +5,13 @@ use bevy_ecs::{
|
|||
system::Query,
|
||||
world::World,
|
||||
};
|
||||
use criterion::{criterion_group, criterion_main, Criterion};
|
||||
|
||||
criterion_group!(
|
||||
benches,
|
||||
run_criteria_yes,
|
||||
run_criteria_no,
|
||||
run_criteria_yes_with_labels,
|
||||
run_criteria_no_with_labels,
|
||||
run_criteria_yes_with_query,
|
||||
run_criteria_yes_with_resource
|
||||
);
|
||||
criterion_main!(benches);
|
||||
use criterion::Criterion;
|
||||
|
||||
fn run_stage(stage: &mut SystemStage, world: &mut World) {
|
||||
stage.run(world);
|
||||
}
|
||||
|
||||
fn run_criteria_yes(criterion: &mut Criterion) {
|
||||
pub fn run_criteria_yes(criterion: &mut Criterion) {
|
||||
let mut world = World::new();
|
||||
let mut group = criterion.benchmark_group("run_criteria/yes");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
|
@ -54,7 +43,7 @@ fn run_criteria_yes(criterion: &mut Criterion) {
|
|||
group.finish();
|
||||
}
|
||||
|
||||
fn run_criteria_no(criterion: &mut Criterion) {
|
||||
pub fn run_criteria_no(criterion: &mut Criterion) {
|
||||
let mut world = World::new();
|
||||
let mut group = criterion.benchmark_group("run_criteria/no");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
|
@ -85,7 +74,7 @@ fn run_criteria_no(criterion: &mut Criterion) {
|
|||
group.finish();
|
||||
}
|
||||
|
||||
fn run_criteria_yes_with_labels(criterion: &mut Criterion) {
|
||||
pub fn run_criteria_yes_with_labels(criterion: &mut Criterion) {
|
||||
let mut world = World::new();
|
||||
let mut group = criterion.benchmark_group("run_criteria/yes_with_labels");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
|
@ -116,7 +105,7 @@ fn run_criteria_yes_with_labels(criterion: &mut Criterion) {
|
|||
group.finish();
|
||||
}
|
||||
|
||||
fn run_criteria_no_with_labels(criterion: &mut Criterion) {
|
||||
pub fn run_criteria_no_with_labels(criterion: &mut Criterion) {
|
||||
let mut world = World::new();
|
||||
let mut group = criterion.benchmark_group("run_criteria/no_with_labels");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
|
@ -150,7 +139,7 @@ fn run_criteria_no_with_labels(criterion: &mut Criterion) {
|
|||
#[derive(Component)]
|
||||
struct TestBool(pub bool);
|
||||
|
||||
fn run_criteria_yes_with_query(criterion: &mut Criterion) {
|
||||
pub fn run_criteria_yes_with_query(criterion: &mut Criterion) {
|
||||
let mut world = World::new();
|
||||
world.spawn().insert(TestBool(true));
|
||||
let mut group = criterion.benchmark_group("run_criteria/yes_using_query");
|
||||
|
@ -187,7 +176,7 @@ fn run_criteria_yes_with_query(criterion: &mut Criterion) {
|
|||
group.finish();
|
||||
}
|
||||
|
||||
fn run_criteria_yes_with_resource(criterion: &mut Criterion) {
|
||||
pub fn run_criteria_yes_with_resource(criterion: &mut Criterion) {
|
||||
let mut world = World::new();
|
||||
world.insert_resource(TestBool(true));
|
||||
let mut group = criterion.benchmark_group("run_criteria/yes_using_resource");
|
|
@ -1,11 +1,63 @@
|
|||
use bevy_app::App;
|
||||
use bevy_ecs::prelude::*;
|
||||
use criterion::{criterion_group, criterion_main, Criterion};
|
||||
use criterion::Criterion;
|
||||
|
||||
criterion_group!(benches, build_schedule);
|
||||
criterion_main!(benches);
|
||||
pub fn schedule(c: &mut Criterion) {
|
||||
#[derive(Component)]
|
||||
struct A(f32);
|
||||
#[derive(Component)]
|
||||
struct B(f32);
|
||||
#[derive(Component)]
|
||||
struct C(f32);
|
||||
#[derive(Component)]
|
||||
struct D(f32);
|
||||
#[derive(Component)]
|
||||
struct E(f32);
|
||||
|
||||
fn build_schedule(criterion: &mut Criterion) {
|
||||
fn ab(mut query: Query<(&mut A, &mut B)>) {
|
||||
query.for_each_mut(|(mut a, mut b)| {
|
||||
std::mem::swap(&mut a.0, &mut b.0);
|
||||
});
|
||||
}
|
||||
|
||||
fn cd(mut query: Query<(&mut C, &mut D)>) {
|
||||
query.for_each_mut(|(mut c, mut d)| {
|
||||
std::mem::swap(&mut c.0, &mut d.0);
|
||||
});
|
||||
}
|
||||
|
||||
fn ce(mut query: Query<(&mut C, &mut E)>) {
|
||||
query.for_each_mut(|(mut c, mut e)| {
|
||||
std::mem::swap(&mut c.0, &mut e.0);
|
||||
});
|
||||
}
|
||||
|
||||
let mut group = c.benchmark_group("schedule");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(4));
|
||||
group.bench_function("base", |b| {
|
||||
let mut world = World::default();
|
||||
|
||||
world.spawn_batch((0..10000).map(|_| (A(0.0), B(0.0))));
|
||||
|
||||
world.spawn_batch((0..10000).map(|_| (A(0.0), B(0.0), C(0.0))));
|
||||
|
||||
world.spawn_batch((0..10000).map(|_| (A(0.0), B(0.0), C(0.0), D(0.0))));
|
||||
|
||||
world.spawn_batch((0..10000).map(|_| (A(0.0), B(0.0), C(0.0), E(0.0))));
|
||||
|
||||
let mut stage = SystemStage::parallel();
|
||||
stage.add_system(ab);
|
||||
stage.add_system(cd);
|
||||
stage.add_system(ce);
|
||||
stage.run(&mut world);
|
||||
|
||||
b.iter(move || stage.run(&mut world));
|
||||
});
|
||||
group.finish();
|
||||
}
|
||||
|
||||
pub fn build_schedule(criterion: &mut Criterion) {
|
||||
// empty system
|
||||
fn empty_system() {}
|
||||
|
|
@ -4,10 +4,7 @@ use bevy_ecs::{
|
|||
system::Query,
|
||||
world::World,
|
||||
};
|
||||
use criterion::{criterion_group, criterion_main, Criterion};
|
||||
|
||||
criterion_group!(benches, empty_systems, busy_systems, contrived);
|
||||
criterion_main!(benches);
|
||||
use criterion::Criterion;
|
||||
|
||||
fn run_stage(stage: &mut SystemStage, world: &mut World) {
|
||||
stage.run(world);
|
||||
|
@ -26,7 +23,7 @@ struct E(f32);
|
|||
|
||||
const ENTITY_BUNCH: usize = 5000;
|
||||
|
||||
fn empty_systems(criterion: &mut Criterion) {
|
||||
pub fn empty_systems(criterion: &mut Criterion) {
|
||||
let mut world = World::new();
|
||||
let mut group = criterion.benchmark_group("empty_systems");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
|
@ -64,7 +61,7 @@ fn empty_systems(criterion: &mut Criterion) {
|
|||
group.finish()
|
||||
}
|
||||
|
||||
fn busy_systems(criterion: &mut Criterion) {
|
||||
pub fn busy_systems(criterion: &mut Criterion) {
|
||||
fn ab(mut q: Query<(&mut A, &mut B)>) {
|
||||
q.for_each_mut(|(mut a, mut b)| {
|
||||
std::mem::swap(&mut a.0, &mut b.0);
|
||||
|
@ -113,7 +110,7 @@ fn busy_systems(criterion: &mut Criterion) {
|
|||
group.finish()
|
||||
}
|
||||
|
||||
fn contrived(criterion: &mut Criterion) {
|
||||
pub fn contrived(criterion: &mut Criterion) {
|
||||
fn s_0(mut q_0: Query<(&mut A, &mut B)>) {
|
||||
q_0.for_each_mut(|(mut c_0, mut c_1)| {
|
||||
std::mem::swap(&mut c_0.0, &mut c_1.0);
|
|
@ -4,20 +4,7 @@ use bevy_ecs::{
|
|||
system::{Command, CommandQueue, Commands},
|
||||
world::World,
|
||||
};
|
||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||
|
||||
criterion_group!(
|
||||
benches,
|
||||
empty_commands,
|
||||
spawn_commands,
|
||||
insert_commands,
|
||||
fake_commands,
|
||||
zero_sized_commands,
|
||||
medium_sized_commands,
|
||||
large_sized_commands,
|
||||
get_or_spawn
|
||||
);
|
||||
criterion_main!(benches);
|
||||
use criterion::{black_box, Criterion};
|
||||
|
||||
#[derive(Component)]
|
||||
struct A;
|
||||
|
@ -26,7 +13,7 @@ struct B;
|
|||
#[derive(Component)]
|
||||
struct C;
|
||||
|
||||
fn empty_commands(criterion: &mut Criterion) {
|
||||
pub fn empty_commands(criterion: &mut Criterion) {
|
||||
let mut group = criterion.benchmark_group("empty_commands");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(4));
|
||||
|
@ -43,7 +30,7 @@ fn empty_commands(criterion: &mut Criterion) {
|
|||
group.finish();
|
||||
}
|
||||
|
||||
fn spawn_commands(criterion: &mut Criterion) {
|
||||
pub fn spawn_commands(criterion: &mut Criterion) {
|
||||
let mut group = criterion.benchmark_group("spawn_commands");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(4));
|
||||
|
@ -89,7 +76,7 @@ struct Matrix([[f32; 4]; 4]);
|
|||
#[derive(Default, Component)]
|
||||
struct Vec3([f32; 3]);
|
||||
|
||||
fn insert_commands(criterion: &mut Criterion) {
|
||||
pub fn insert_commands(criterion: &mut Criterion) {
|
||||
let mut group = criterion.benchmark_group("insert_commands");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(4));
|
||||
|
@ -154,7 +141,7 @@ impl Command for FakeCommandB {
|
|||
}
|
||||
}
|
||||
|
||||
fn fake_commands(criterion: &mut Criterion) {
|
||||
pub fn fake_commands(criterion: &mut Criterion) {
|
||||
let mut group = criterion.benchmark_group("fake_commands");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(4));
|
||||
|
@ -200,7 +187,7 @@ impl Default for LargeStruct {
|
|||
}
|
||||
}
|
||||
|
||||
fn sized_commands_impl<T: Default + Command>(criterion: &mut Criterion) {
|
||||
pub fn sized_commands_impl<T: Default + Command>(criterion: &mut Criterion) {
|
||||
let mut group =
|
||||
criterion.benchmark_group(format!("sized_commands_{}_bytes", std::mem::size_of::<T>()));
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
|
@ -225,19 +212,19 @@ fn sized_commands_impl<T: Default + Command>(criterion: &mut Criterion) {
|
|||
group.finish();
|
||||
}
|
||||
|
||||
fn zero_sized_commands(criterion: &mut Criterion) {
|
||||
pub fn zero_sized_commands(criterion: &mut Criterion) {
|
||||
sized_commands_impl::<SizedCommand<()>>(criterion);
|
||||
}
|
||||
|
||||
fn medium_sized_commands(criterion: &mut Criterion) {
|
||||
pub fn medium_sized_commands(criterion: &mut Criterion) {
|
||||
sized_commands_impl::<SizedCommand<(u32, u32, u32)>>(criterion);
|
||||
}
|
||||
|
||||
fn large_sized_commands(criterion: &mut Criterion) {
|
||||
pub fn large_sized_commands(criterion: &mut Criterion) {
|
||||
sized_commands_impl::<SizedCommand<LargeStruct>>(criterion);
|
||||
}
|
||||
|
||||
fn get_or_spawn(criterion: &mut Criterion) {
|
||||
pub fn get_or_spawn(criterion: &mut Criterion) {
|
||||
let mut group = criterion.benchmark_group("get_or_spawn");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(4));
|
27
benches/benches/bevy_ecs/world/mod.rs
Normal file
27
benches/benches/bevy_ecs/world/mod.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
use criterion::criterion_group;
|
||||
|
||||
mod commands;
|
||||
mod world_get;
|
||||
|
||||
use commands::*;
|
||||
use world_get::*;
|
||||
|
||||
criterion_group!(
|
||||
world_benches,
|
||||
empty_commands,
|
||||
spawn_commands,
|
||||
insert_commands,
|
||||
fake_commands,
|
||||
zero_sized_commands,
|
||||
medium_sized_commands,
|
||||
large_sized_commands,
|
||||
get_or_spawn,
|
||||
world_entity,
|
||||
world_get,
|
||||
world_query_get,
|
||||
world_query_iter,
|
||||
world_query_for_each,
|
||||
query_get_component_simple,
|
||||
query_get_component,
|
||||
query_get,
|
||||
);
|
|
@ -1,26 +1,15 @@
|
|||
use bevy_ecs::{
|
||||
bundle::Bundle,
|
||||
component::Component,
|
||||
entity::Entity,
|
||||
prelude::*,
|
||||
system::{Query, SystemState},
|
||||
bundle::Bundle,
|
||||
world::World,
|
||||
};
|
||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||
use criterion::{black_box, Criterion};
|
||||
use rand::{prelude::SliceRandom, SeedableRng};
|
||||
use rand_chacha::ChaCha8Rng;
|
||||
|
||||
criterion_group!(
|
||||
benches,
|
||||
world_entity,
|
||||
world_get,
|
||||
world_query_get,
|
||||
world_query_iter,
|
||||
world_query_for_each,
|
||||
query_get_component,
|
||||
query_get,
|
||||
);
|
||||
criterion_main!(benches);
|
||||
|
||||
#[derive(Component, Default)]
|
||||
#[component(storage = "Table")]
|
||||
struct Table(f32);
|
||||
|
@ -52,7 +41,7 @@ fn setup_wide<T: Bundle + Default>(entity_count: u32) -> World {
|
|||
black_box(world)
|
||||
}
|
||||
|
||||
fn world_entity(criterion: &mut Criterion) {
|
||||
pub fn world_entity(criterion: &mut Criterion) {
|
||||
let mut group = criterion.benchmark_group("world_entity");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(4));
|
||||
|
@ -73,7 +62,7 @@ fn world_entity(criterion: &mut Criterion) {
|
|||
group.finish();
|
||||
}
|
||||
|
||||
fn world_get(criterion: &mut Criterion) {
|
||||
pub fn world_get(criterion: &mut Criterion) {
|
||||
let mut group = criterion.benchmark_group("world_get");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(4));
|
||||
|
@ -104,7 +93,7 @@ fn world_get(criterion: &mut Criterion) {
|
|||
group.finish();
|
||||
}
|
||||
|
||||
fn world_query_get(criterion: &mut Criterion) {
|
||||
pub fn world_query_get(criterion: &mut Criterion) {
|
||||
let mut group = criterion.benchmark_group("world_query_get");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(4));
|
||||
|
@ -157,37 +146,40 @@ fn world_query_get(criterion: &mut Criterion) {
|
|||
}
|
||||
});
|
||||
});
|
||||
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>,
|
||||
)>();
|
||||
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);
|
||||
assert!(query.get(&world, entity).is_ok());
|
||||
}
|
||||
});
|
||||
});
|
||||
bencher.iter(|| {
|
||||
for i in 0..entity_count {
|
||||
let entity = Entity::from_raw(i);
|
||||
assert!(query.get(&world, entity).is_ok());
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
group.finish();
|
||||
}
|
||||
|
||||
fn world_query_iter(criterion: &mut Criterion) {
|
||||
pub fn world_query_iter(criterion: &mut Criterion) {
|
||||
let mut group = criterion.benchmark_group("world_query_iter");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(4));
|
||||
|
@ -226,7 +218,7 @@ fn world_query_iter(criterion: &mut Criterion) {
|
|||
group.finish();
|
||||
}
|
||||
|
||||
fn world_query_for_each(criterion: &mut Criterion) {
|
||||
pub fn world_query_for_each(criterion: &mut Criterion) {
|
||||
let mut group = criterion.benchmark_group("world_query_for_each");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(4));
|
||||
|
@ -265,7 +257,49 @@ fn world_query_for_each(criterion: &mut Criterion) {
|
|||
group.finish();
|
||||
}
|
||||
|
||||
fn query_get_component(criterion: &mut Criterion) {
|
||||
pub fn query_get_component_simple(criterion: &mut Criterion) {
|
||||
#[derive(Component)]
|
||||
struct A(f32);
|
||||
|
||||
let mut group = criterion.benchmark_group("query_get_component_simple");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(4));
|
||||
|
||||
group.bench_function("unchecked", |bencher| {
|
||||
let mut world = World::new();
|
||||
|
||||
let entity = world.spawn().insert(A(0.0)).id();
|
||||
let mut query = world.query::<&mut A>();
|
||||
|
||||
bencher.iter(|| {
|
||||
for _x in 0..100000 {
|
||||
let mut a = unsafe { query.get_unchecked(&mut world, entity).unwrap() };
|
||||
a.0 += 1.0;
|
||||
}
|
||||
});
|
||||
});
|
||||
group.bench_function("system", |bencher| {
|
||||
let mut world = World::new();
|
||||
|
||||
let entity = world.spawn().insert(A(0.0)).id();
|
||||
fn query_system(In(entity): In<Entity>, mut query: Query<&mut A>) {
|
||||
for _ in 0..100_000 {
|
||||
let mut a = query.get_mut(entity).unwrap();
|
||||
a.0 += 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
let mut system = IntoSystem::into_system(query_system);
|
||||
system.initialize(&mut world);
|
||||
system.update_archetype_component_access(&world);
|
||||
|
||||
bencher.iter(|| system.run(entity, &mut world));
|
||||
});
|
||||
|
||||
group.finish();
|
||||
}
|
||||
|
||||
pub fn query_get_component(criterion: &mut Criterion) {
|
||||
let mut group = criterion.benchmark_group("query_get_component");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(4));
|
||||
|
@ -320,7 +354,7 @@ fn query_get_component(criterion: &mut Criterion) {
|
|||
group.finish();
|
||||
}
|
||||
|
||||
fn query_get(criterion: &mut Criterion) {
|
||||
pub fn query_get(criterion: &mut Criterion) {
|
||||
let mut group = criterion.benchmark_group("query_get");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(4));
|
Loading…
Reference in a new issue