mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
Re-add ECS benchmark suite (#4332)
# Objective - Benchmarks are good. - Licensing situation appears to be [cleared up](https://github.com/bevyengine/bevy/pull/4225#issuecomment-1078710209). ## Solution - Add the benchmark suite back in - Suggested PR title: "Revert "Revert "Add cart's fork of ecs_bench_suite (#4225)" (#4252)" Co-authored-by: Daniel McNab <36049421+DJMcNab@users.noreply.github.com>
This commit is contained in:
parent
6844a6f4fd
commit
1b63d949ea
22 changed files with 996 additions and 0 deletions
|
@ -7,10 +7,16 @@ publish = false
|
|||
license = "MIT OR Apache-2.0"
|
||||
|
||||
[dev-dependencies]
|
||||
glam = "0.20"
|
||||
criterion = "0.3"
|
||||
bevy_ecs = { path = "../crates/bevy_ecs" }
|
||||
bevy_tasks = { path = "../crates/bevy_tasks" }
|
||||
|
||||
[[bench]]
|
||||
name = "ecs_bench_suite"
|
||||
path = "benches/bevy_ecs/ecs_bench_suite/mod.rs"
|
||||
harness = false
|
||||
|
||||
[[bench]]
|
||||
name = "system_stage"
|
||||
path = "benches/bevy_ecs/stages.rs"
|
||||
|
|
30
benches/benches/bevy_ecs/ecs_bench_suite/add_remove.rs
Normal file
30
benches/benches/bevy_ecs/ecs_bench_suite/add_remove.rs
Normal file
|
@ -0,0 +1,30 @@
|
|||
use bevy::prelude::*;
|
||||
|
||||
#[derive(Component)]
|
||||
struct A(f32);
|
||||
#[derive(Component)]
|
||||
struct B(f32);
|
||||
|
||||
pub struct Benchmark(World, Vec<Entity>);
|
||||
|
||||
impl Benchmark {
|
||||
pub fn new() -> Self {
|
||||
let mut world = World::default();
|
||||
|
||||
let entities = world
|
||||
.spawn_batch((0..10000).map(|_| (A(0.0),)))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Self(world, entities)
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
for entity in &self.1 {
|
||||
self.0.insert_one(*entity, B(0.0)).unwrap();
|
||||
}
|
||||
|
||||
for entity in &self.1 {
|
||||
self.0.remove_one::<B>(*entity).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
use bevy_ecs::prelude::*;
|
||||
use glam::*;
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct A(Mat4);
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct B(Mat4);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct C(Mat4);
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct D(Mat4);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct E(Mat4);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
#[component(storage = "SparseSet")]
|
||||
struct F(Mat4);
|
||||
pub struct Benchmark(World, Vec<Entity>);
|
||||
|
||||
impl Benchmark {
|
||||
pub fn new() -> Self {
|
||||
let mut world = World::default();
|
||||
let mut entities = Vec::with_capacity(10_000);
|
||||
for _ in 0..10_000 {
|
||||
entities.push(
|
||||
world
|
||||
.spawn()
|
||||
.insert_bundle((
|
||||
A(Mat4::from_scale(Vec3::ONE)),
|
||||
B(Mat4::from_scale(Vec3::ONE)),
|
||||
C(Mat4::from_scale(Vec3::ONE)),
|
||||
D(Mat4::from_scale(Vec3::ONE)),
|
||||
E(Mat4::from_scale(Vec3::ONE)),
|
||||
))
|
||||
.id(),
|
||||
);
|
||||
}
|
||||
|
||||
Self(world, entities)
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
for entity in &self.1 {
|
||||
self.0
|
||||
.entity_mut(*entity)
|
||||
.insert(F(Mat4::from_scale(Vec3::ONE)));
|
||||
}
|
||||
|
||||
for entity in &self.1 {
|
||||
self.0.entity_mut(*entity).remove::<F>();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
use bevy_ecs::prelude::*;
|
||||
use glam::*;
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct A(Mat4);
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct B(Mat4);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct C(Mat4);
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct D(Mat4);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct E(Mat4);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct F(Mat4);
|
||||
pub struct Benchmark(World, Vec<Entity>);
|
||||
|
||||
impl Benchmark {
|
||||
pub fn new() -> Self {
|
||||
let mut world = World::default();
|
||||
let mut entities = Vec::with_capacity(10_000);
|
||||
for _ in 0..10_000 {
|
||||
entities.push(
|
||||
world
|
||||
.spawn()
|
||||
.insert_bundle((
|
||||
A(Mat4::from_scale(Vec3::ONE)),
|
||||
B(Mat4::from_scale(Vec3::ONE)),
|
||||
C(Mat4::from_scale(Vec3::ONE)),
|
||||
D(Mat4::from_scale(Vec3::ONE)),
|
||||
E(Mat4::from_scale(Vec3::ONE)),
|
||||
))
|
||||
.id(),
|
||||
);
|
||||
}
|
||||
|
||||
Self(world, entities)
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
for entity in &self.1 {
|
||||
self.0
|
||||
.entity_mut(*entity)
|
||||
.insert(F(Mat4::from_scale(Vec3::ONE)));
|
||||
}
|
||||
|
||||
for entity in &self.1 {
|
||||
self.0.entity_mut(*entity).remove::<F>();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
use bevy_ecs::prelude::*;
|
||||
|
||||
#[derive(Component)]
|
||||
struct A(f32);
|
||||
#[derive(Component)]
|
||||
#[component(storage = "SparseSet")]
|
||||
struct B(f32);
|
||||
|
||||
pub struct Benchmark(World, Vec<Entity>);
|
||||
|
||||
impl Benchmark {
|
||||
pub fn new() -> Self {
|
||||
let mut world = World::default();
|
||||
let mut entities = Vec::with_capacity(10_000);
|
||||
for _ in 0..10_000 {
|
||||
entities.push(world.spawn().insert(A(0.0)).id());
|
||||
}
|
||||
|
||||
Self(world, entities)
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
for entity in &self.1 {
|
||||
self.0.entity_mut(*entity).insert(B(0.0));
|
||||
}
|
||||
|
||||
for entity in &self.1 {
|
||||
self.0.entity_mut(*entity).remove::<B>();
|
||||
}
|
||||
}
|
||||
}
|
30
benches/benches/bevy_ecs/ecs_bench_suite/add_remove_table.rs
Normal file
30
benches/benches/bevy_ecs/ecs_bench_suite/add_remove_table.rs
Normal file
|
@ -0,0 +1,30 @@
|
|||
use bevy_ecs::prelude::*;
|
||||
|
||||
#[derive(Component)]
|
||||
struct A(f32);
|
||||
#[derive(Component)]
|
||||
struct B(f32);
|
||||
|
||||
pub struct Benchmark(World, Vec<Entity>);
|
||||
|
||||
impl Benchmark {
|
||||
pub fn new() -> Self {
|
||||
let mut world = World::default();
|
||||
let mut entities = Vec::with_capacity(10_000);
|
||||
for _ in 0..10_000 {
|
||||
entities.push(world.spawn().insert(A(0.0)).id());
|
||||
}
|
||||
|
||||
Self(world, entities)
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
for entity in &self.1 {
|
||||
self.0.entity_mut(*entity).insert(B(0.0));
|
||||
}
|
||||
|
||||
for entity in &self.1 {
|
||||
self.0.entity_mut(*entity).remove::<B>();
|
||||
}
|
||||
}
|
||||
}
|
35
benches/benches/bevy_ecs/ecs_bench_suite/frag_iter.rs
Normal file
35
benches/benches/bevy_ecs/ecs_bench_suite/frag_iter.rs
Normal file
|
@ -0,0 +1,35 @@
|
|||
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(1.0)));
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
struct Data(f32);
|
||||
|
||||
pub struct Benchmark<'w>(World, QueryState<&'w mut Data>);
|
||||
|
||||
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::<&mut Data>();
|
||||
Self(world, query)
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
for mut data in self.1.iter_mut(&mut self.0) {
|
||||
data.0 *= 2.0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
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(1.0)));
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
struct Data(f32);
|
||||
|
||||
pub struct Benchmark<'w>(World, QueryState<&'w mut Data>);
|
||||
|
||||
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::<&mut Data>();
|
||||
Self(world, query)
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
self.1.for_each_mut(&mut self.0, |mut data| {
|
||||
data.0 *= 2.0;
|
||||
});
|
||||
}
|
||||
}
|
23
benches/benches/bevy_ecs/ecs_bench_suite/get_component.rs
Normal file
23
benches/benches/bevy_ecs/ecs_bench_suite/get_component.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
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);
|
||||
for archetype in world.archetypes().iter() {
|
||||
system.new_archetype(archetype);
|
||||
}
|
||||
Self(world, entity, Box::new(system))
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
self.2.run(self.1, &mut self.0);
|
||||
}
|
||||
}
|
55
benches/benches/bevy_ecs/ecs_bench_suite/heavy_compute.rs
Normal file
55
benches/benches/bevy_ecs/ecs_bench_suite/heavy_compute.rs
Normal file
|
@ -0,0 +1,55 @@
|
|||
use bevy_ecs::prelude::*;
|
||||
use bevy_tasks::TaskPool;
|
||||
use glam::*;
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Position(Vec3);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Rotation(Vec3);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Velocity(Vec3);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Transform(Mat4);
|
||||
|
||||
pub struct Benchmark(World, Box<dyn System<In = (), Out = ()>>);
|
||||
|
||||
impl Benchmark {
|
||||
pub fn new() -> Self {
|
||||
let mut world = World::default();
|
||||
|
||||
world.spawn_batch((0..1000).map(|_| {
|
||||
(
|
||||
Transform(Mat4::from_axis_angle(Vec3::X, 1.2)),
|
||||
Position(Vec3::X),
|
||||
Rotation(Vec3::X),
|
||||
Velocity(Vec3::X),
|
||||
)
|
||||
}));
|
||||
|
||||
fn sys(task_pool: Res<TaskPool>, mut query: Query<(&mut Position, &mut Transform)>) {
|
||||
query.par_for_each_mut(&task_pool, 128, |(mut pos, mut mat)| {
|
||||
for _ in 0..100 {
|
||||
mat.0 = mat.0.inverse();
|
||||
}
|
||||
|
||||
pos.0 = mat.0.transform_vector3(pos.0);
|
||||
});
|
||||
}
|
||||
|
||||
world.insert_resource(TaskPool::default());
|
||||
let mut system = IntoSystem::into_system(sys);
|
||||
system.initialize(&mut world);
|
||||
for archetype in world.archetypes().iter() {
|
||||
system.new_archetype(archetype);
|
||||
}
|
||||
|
||||
Self(world, Box::new(system))
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
self.1.run((), &mut self.0);
|
||||
}
|
||||
}
|
174
benches/benches/bevy_ecs/ecs_bench_suite/mod.rs
Normal file
174
benches/benches/bevy_ecs/ecs_bench_suite/mod.rs
Normal file
|
@ -0,0 +1,174 @@
|
|||
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_foreach;
|
||||
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_foreach;
|
||||
mod simple_iter_sparse;
|
||||
mod simple_iter_sparse_foreach;
|
||||
mod simple_iter_system;
|
||||
mod sparse_frag_iter;
|
||||
mod sparse_frag_iter_foreach;
|
||||
|
||||
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("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("foreach", |b| {
|
||||
let mut bench = simple_iter_foreach::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.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("foreach", |b| {
|
||||
let mut bench = frag_iter_foreach::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("foreach", |b| {
|
||||
let mut bench = sparse_frag_iter_foreach::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);
|
58
benches/benches/bevy_ecs/ecs_bench_suite/schedule.rs
Normal file
58
benches/benches/bevy_ecs/ecs_bench_suite/schedule.rs
Normal file
|
@ -0,0 +1,58 @@
|
|||
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);
|
||||
}
|
||||
}
|
34
benches/benches/bevy_ecs/ecs_bench_suite/simple_insert.rs
Normal file
34
benches/benches/bevy_ecs/ecs_bench_suite/simple_insert.rs
Normal file
|
@ -0,0 +1,34 @@
|
|||
use bevy_ecs::prelude::*;
|
||||
use glam::*;
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Transform(Mat4);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Position(Vec3);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Rotation(Vec3);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Velocity(Vec3);
|
||||
|
||||
pub struct Benchmark;
|
||||
|
||||
impl Benchmark {
|
||||
pub fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
let mut world = World::new();
|
||||
world.spawn_batch((0..10_000).map(|_| {
|
||||
(
|
||||
Transform(Mat4::from_scale(Vec3::ONE)),
|
||||
Position(Vec3::X),
|
||||
Rotation(Vec3::X),
|
||||
Velocity(Vec3::X),
|
||||
)
|
||||
}));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
use bevy_ecs::prelude::*;
|
||||
use glam::*;
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Transform(Mat4);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Position(Vec3);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Rotation(Vec3);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Velocity(Vec3);
|
||||
|
||||
pub struct Benchmark;
|
||||
|
||||
impl Benchmark {
|
||||
pub fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
let mut world = World::new();
|
||||
for _ in 0..10_000 {
|
||||
world.spawn().insert_bundle((
|
||||
Transform(Mat4::from_scale(Vec3::ONE)),
|
||||
Position(Vec3::X),
|
||||
Rotation(Vec3::X),
|
||||
Velocity(Vec3::X),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
41
benches/benches/bevy_ecs/ecs_bench_suite/simple_iter.rs
Normal file
41
benches/benches/bevy_ecs/ecs_bench_suite/simple_iter.rs
Normal file
|
@ -0,0 +1,41 @@
|
|||
use bevy_ecs::prelude::*;
|
||||
use glam::*;
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Transform(Mat4);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Position(Vec3);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Rotation(Vec3);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Velocity(Vec3);
|
||||
|
||||
pub struct Benchmark<'w>(World, QueryState<(&'w Velocity, &'w mut Position)>);
|
||||
|
||||
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)),
|
||||
Position(Vec3::X),
|
||||
Rotation(Vec3::X),
|
||||
Velocity(Vec3::X),
|
||||
));
|
||||
}
|
||||
|
||||
let query = world.query::<(&Velocity, &mut Position)>();
|
||||
Self(world, query)
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
for (velocity, mut position) in self.1.iter_mut(&mut self.0) {
|
||||
position.0 += velocity.0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
use bevy_ecs::prelude::*;
|
||||
use glam::*;
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Transform(Mat4);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Position(Vec3);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Rotation(Vec3);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Velocity(Vec3);
|
||||
|
||||
pub struct Benchmark<'w>(World, QueryState<(&'w Velocity, &'w mut Position)>);
|
||||
|
||||
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)),
|
||||
Position(Vec3::X),
|
||||
Rotation(Vec3::X),
|
||||
Velocity(Vec3::X),
|
||||
));
|
||||
}
|
||||
|
||||
let query = world.query::<(&Velocity, &mut Position)>();
|
||||
Self(world, query)
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
self.1
|
||||
.for_each_mut(&mut self.0, |(velocity, mut position)| {
|
||||
position.0 += velocity.0;
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
use bevy_ecs::prelude::*;
|
||||
use glam::*;
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Transform(Mat4);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
#[component(storage = "SparseSet")]
|
||||
struct Position(Vec3);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Rotation(Vec3);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
#[component(storage = "SparseSet")]
|
||||
struct Velocity(Vec3);
|
||||
|
||||
pub struct Benchmark<'w>(World, QueryState<(&'w Velocity, &'w mut Position)>);
|
||||
|
||||
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)),
|
||||
Position(Vec3::X),
|
||||
Rotation(Vec3::X),
|
||||
Velocity(Vec3::X),
|
||||
));
|
||||
}
|
||||
|
||||
let query = world.query::<(&Velocity, &mut Position)>();
|
||||
Self(world, query)
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
for (velocity, mut position) in self.1.iter_mut(&mut self.0) {
|
||||
position.0 += velocity.0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
use bevy_ecs::prelude::*;
|
||||
use glam::*;
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Transform(Mat4);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
#[component(storage = "SparseSet")]
|
||||
struct Position(Vec3);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Rotation(Vec3);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
#[component(storage = "SparseSet")]
|
||||
struct Velocity(Vec3);
|
||||
|
||||
pub struct Benchmark<'w>(World, QueryState<(&'w Velocity, &'w mut Position)>);
|
||||
|
||||
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)),
|
||||
Position(Vec3::X),
|
||||
Rotation(Vec3::X),
|
||||
Velocity(Vec3::X),
|
||||
));
|
||||
}
|
||||
|
||||
let query = world.query::<(&Velocity, &mut Position)>();
|
||||
Self(world, query)
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
self.1
|
||||
.for_each_mut(&mut self.0, |(velocity, mut position)| {
|
||||
position.0 += velocity.0;
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
use bevy_ecs::prelude::*;
|
||||
use glam::*;
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Transform(Mat4);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Position(Vec3);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Rotation(Vec3);
|
||||
|
||||
#[derive(Component, Copy, Clone)]
|
||||
struct Velocity(Vec3);
|
||||
|
||||
pub struct Benchmark(World, Box<dyn System<In = (), Out = ()>>);
|
||||
|
||||
impl Benchmark {
|
||||
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)),
|
||||
Position(Vec3::X),
|
||||
Rotation(Vec3::X),
|
||||
Velocity(Vec3::X),
|
||||
));
|
||||
}
|
||||
|
||||
fn query_system(mut query: Query<(&Velocity, &mut Position)>) {
|
||||
for (velocity, mut position) in query.iter_mut() {
|
||||
position.0 += velocity.0;
|
||||
}
|
||||
}
|
||||
|
||||
let mut system = IntoSystem::into_system(query_system);
|
||||
system.initialize(&mut world);
|
||||
for archetype in world.archetypes().iter() {
|
||||
system.new_archetype(archetype);
|
||||
}
|
||||
Self(world, Box::new(system))
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
self.1.run((), &mut self.0);
|
||||
}
|
||||
}
|
46
benches/benches/bevy_ecs/ecs_bench_suite/sparse_frag_iter.rs
Normal file
46
benches/benches/bevy_ecs/ecs_bench_suite/sparse_frag_iter.rs
Normal file
|
@ -0,0 +1,46 @@
|
|||
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(f32);
|
||||
|
||||
pub struct Benchmark<'w>(World, QueryState<&'w mut Data>);
|
||||
|
||||
impl<'w> Benchmark<'w> {
|
||||
pub fn new() -> Self {
|
||||
let mut world = World::new();
|
||||
|
||||
for _ in 0..5 {
|
||||
world.spawn().insert(Data(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::<&mut Data>();
|
||||
Self(world, query)
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
for mut data in self.1.iter_mut(&mut self.0) {
|
||||
data.0 *= 2.0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
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(f32);
|
||||
|
||||
pub struct Benchmark<'w>(World, QueryState<&'w mut Data>);
|
||||
|
||||
impl<'w> Benchmark<'w> {
|
||||
pub fn new() -> Self {
|
||||
let mut world = World::new();
|
||||
for _ in 0..5 {
|
||||
world.spawn().insert(Data(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::<&mut Data>();
|
||||
Self(world, query)
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
self.1.for_each_mut(&mut self.0, |mut data| {
|
||||
data.0 *= 2.0;
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue