Skip to content

Commit

Permalink
Add cart's fork of ecs_bench_suite (bevyengine#4225)
Browse files Browse the repository at this point in the history
# Objective
Better benchmarking for ECS. Fix bevyengine#2062.

## Solution
Port @cart's fork of ecs_bench_suite to the official bench suite for bevy_ecs, replace cgmath with glam, update to latest bevy.
  • Loading branch information
james7132 committed Mar 19, 2022
1 parent ac8bbaf commit 08ef2f0
Show file tree
Hide file tree
Showing 22 changed files with 996 additions and 0 deletions.
6 changes: 6 additions & 0 deletions benches/Cargo.toml
Expand Up @@ -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"
Expand Down
30 changes: 30 additions & 0 deletions benches/benches/bevy_ecs/ecs_bench_suite/add_remove.rs
@@ -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>();
}
}
}
54 changes: 54 additions & 0 deletions benches/benches/bevy_ecs/ecs_bench_suite/add_remove_big_table.rs
@@ -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>();
}
}
}
31 changes: 31 additions & 0 deletions benches/benches/bevy_ecs/ecs_bench_suite/add_remove_sparse_set.rs
@@ -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 changes: 30 additions & 0 deletions benches/benches/bevy_ecs/ecs_bench_suite/add_remove_table.rs
@@ -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 changes: 35 additions & 0 deletions benches/benches/bevy_ecs/ecs_bench_suite/frag_iter.rs
@@ -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;
}
}
}
35 changes: 35 additions & 0 deletions benches/benches/bevy_ecs/ecs_bench_suite/frag_iter_foreach.rs
@@ -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 changes: 23 additions & 0 deletions benches/benches/bevy_ecs/ecs_bench_suite/get_component.rs
@@ -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;
}
}
}
31 changes: 31 additions & 0 deletions benches/benches/bevy_ecs/ecs_bench_suite/get_component_system.rs
@@ -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);
}
}

0 comments on commit 08ef2f0

Please sign in to comment.