Skip to content
This repository was archived by the owner on Nov 27, 2022. It is now read-only.

Commit 70cc0b7

Browse files
authored
Merge pull request #2 from dekuraan/add-specs
Add benchmarking for SPECS
2 parents acea20d + c9bb9b4 commit 70cc0b7

File tree

10 files changed

+378
-0
lines changed

10 files changed

+378
-0
lines changed

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ legion_2_4 = { package = "legion", version = "0.2.4" }
1818
bevy_ecs = "0.1"
1919
hecs = "0.2"
2020
shipyard = "0.4"
21+
specs = {version = "0.16.1", features = ["serde"] }
22+
specs-derive = "0.4.1"
2123

2224
[dev-dependencies]
2325
criterion = "0.3"

benches/benchmarks.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ fn bench_simple_insert(c: &mut Criterion) {
1919
let mut bench = shipyard::simple_insert::Benchmark::new();
2020
b.iter(move || bench.run());
2121
});
22+
group.bench_function("specs", |b| {
23+
let mut bench = specs::simple_insert::Benchmark::new();
24+
b.iter(move || bench.run());
25+
});
2226
}
2327

2428
fn bench_simple_iter(c: &mut Criterion) {
@@ -39,6 +43,10 @@ fn bench_simple_iter(c: &mut Criterion) {
3943
let mut bench = shipyard::simple_iter::Benchmark::new();
4044
b.iter(move || bench.run());
4145
});
46+
group.bench_function("specs", |b| {
47+
let mut bench = specs::simple_iter::Benchmark::new();
48+
b.iter(move || bench.run());
49+
});
4250
}
4351

4452
fn bench_frag_iter_bc(c: &mut Criterion) {
@@ -59,6 +67,10 @@ fn bench_frag_iter_bc(c: &mut Criterion) {
5967
let mut bench = shipyard::frag_iter::Benchmark::new();
6068
b.iter(move || bench.run());
6169
});
70+
group.bench_function("specs", |b| {
71+
let mut bench = specs::frag_iter::Benchmark::new();
72+
b.iter(move || bench.run());
73+
});
6274
}
6375

6476
fn bench_schedule(c: &mut Criterion) {
@@ -79,6 +91,10 @@ fn bench_schedule(c: &mut Criterion) {
7991
let mut bench = shipyard::schedule::Benchmark::new();
8092
b.iter(move || bench.run());
8193
});
94+
group.bench_function("specs", |b| {
95+
let mut bench = specs::schedule::Benchmark::new();
96+
b.iter(move || bench.run());
97+
});
8298
}
8399

84100
fn bench_heavy_compute(c: &mut Criterion) {
@@ -99,6 +115,10 @@ fn bench_heavy_compute(c: &mut Criterion) {
99115
let mut bench = shipyard::heavy_compute::Benchmark::new();
100116
b.iter(move || bench.run());
101117
});
118+
group.bench_function("specs", |b| {
119+
let mut bench = specs::heavy_compute::Benchmark::new();
120+
b.iter(move || bench.run());
121+
});
102122
}
103123

104124
fn bench_add_remove(c: &mut Criterion) {
@@ -115,6 +135,10 @@ fn bench_add_remove(c: &mut Criterion) {
115135
let mut bench = shipyard::add_remove::Benchmark::new();
116136
b.iter(move || bench.run());
117137
});
138+
group.bench_function("specs", |b| {
139+
let mut bench = specs::add_remove::Benchmark::new();
140+
b.iter(move || bench.run());
141+
});
118142

119143
// todo Bevy appears to crash in this benchmark
120144
// group.bench_function("bevy", |b| {

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ pub mod bevy;
44
pub mod legion;
55
pub mod legion_2_4;
66
pub mod shipyard;
7+
pub mod specs;

src/specs/add_remove.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
use specs::prelude::*;
2+
use specs_derive::*;
3+
#[derive(Component)]
4+
#[storage(VecStorage)]
5+
struct A(f32);
6+
#[derive(Component)]
7+
#[storage(VecStorage)]
8+
struct B(f32);
9+
10+
pub struct Benchmark(World, Vec<Entity>);
11+
12+
impl Benchmark {
13+
pub fn new() -> Self {
14+
let mut world = World::new();
15+
world.register::<A>();
16+
world.register::<B>();
17+
let entities = (0..10000)
18+
.map(|_| world.create_entity().with(A(0.0)).build())
19+
.collect();
20+
Self(world, entities)
21+
}
22+
23+
pub fn run(&mut self) {
24+
let mut b_storage = self.0.write_storage::<B>();
25+
for entity in &self.1 {
26+
b_storage.insert(*entity, B(0.0)).unwrap();
27+
}
28+
29+
for entity in &self.1 {
30+
b_storage.remove(*entity);
31+
}
32+
}
33+
}

src/specs/frag_iter.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
use specs::prelude::*;
2+
use specs_derive::*;
3+
4+
macro_rules! create_entities {
5+
($world:ident; $( $variants:ident ),*) => {
6+
$(
7+
#[derive(Component)]
8+
#[storage(VecStorage)]
9+
struct $variants(f32);
10+
$world.register::<$variants>();
11+
(0..20)
12+
.for_each(|_| {$world.create_entity().with($variants(0.0)).with(Data(1.0)).build();});
13+
)*
14+
};
15+
}
16+
#[derive(Component)]
17+
#[storage(VecStorage)]
18+
struct Data(f32);
19+
20+
struct FragIterSystem;
21+
22+
impl<'a> System<'a> for FragIterSystem {
23+
type SystemData = WriteStorage<'a, Data>;
24+
25+
fn run(&mut self, mut data_storage: Self::SystemData) {
26+
for data in (&mut data_storage).join() {
27+
data.0 *= 2.0;
28+
}
29+
}
30+
}
31+
pub struct Benchmark(World, FragIterSystem);
32+
33+
impl Benchmark {
34+
pub fn new() -> Self {
35+
let mut world = World::new();
36+
world.register::<Data>();
37+
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);
38+
39+
Self(world, FragIterSystem)
40+
}
41+
42+
pub fn run(&mut self) {
43+
self.1.run_now(&self.0)
44+
}
45+
}

src/specs/heavy_compute.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
use cgmath::*;
2+
use specs::prelude::*;
3+
use specs_derive::*;
4+
#[derive(Copy, Clone, Component)]
5+
#[storage(VecStorage)]
6+
struct Transform(Matrix4<f32>);
7+
#[derive(Copy, Clone, Component)]
8+
#[storage(VecStorage)]
9+
struct Position(Vector3<f32>);
10+
11+
#[derive(Copy, Clone, Component)]
12+
#[storage(VecStorage)]
13+
struct Rotation(Vector3<f32>);
14+
15+
#[derive(Copy, Clone, Component)]
16+
#[storage(VecStorage)]
17+
struct Velocity(Vector3<f32>);
18+
19+
struct HeavyComputeSystem;
20+
21+
impl<'a> System<'a> for HeavyComputeSystem {
22+
type SystemData = (WriteStorage<'a, Position>, WriteStorage<'a, Transform>);
23+
24+
fn run(&mut self, (mut pos_store, mut mat_store): Self::SystemData) {
25+
use cgmath::Transform;
26+
for (pos, mat) in (&mut pos_store, &mut mat_store).join() {
27+
for _ in 0..100 {
28+
mat.0 = mat.0.invert().unwrap();
29+
}
30+
pos.0 = mat.0.transform_vector(pos.0);
31+
}
32+
}
33+
}
34+
35+
pub struct Benchmark(World, HeavyComputeSystem);
36+
37+
impl Benchmark {
38+
pub fn new() -> Self {
39+
let mut world = World::new();
40+
world.register::<Transform>();
41+
world.register::<Position>();
42+
world.register::<Rotation>();
43+
world.register::<Velocity>();
44+
(0..1000).for_each(|_| {
45+
world
46+
.create_entity()
47+
.with(Transform(Matrix4::<f32>::from_angle_x(Rad(1.2))))
48+
.with(Position(Vector3::unit_x()))
49+
.with(Rotation(Vector3::unit_x()))
50+
.with(Velocity(Vector3::unit_x()))
51+
.build();
52+
});
53+
54+
Self(world, HeavyComputeSystem)
55+
}
56+
57+
pub fn run(&mut self) {
58+
self.1.run_now(&self.0);
59+
}
60+
}

src/specs/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pub mod add_remove;
2+
pub mod frag_iter;
3+
pub mod heavy_compute;
4+
pub mod schedule;
5+
pub mod simple_insert;
6+
pub mod simple_iter;

src/specs/schedule.rs

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
use specs::prelude::*;
2+
use specs_derive::*;
3+
#[derive(Component)]
4+
#[storage(VecStorage)]
5+
struct A(f32);
6+
#[derive(Component)]
7+
#[storage(VecStorage)]
8+
struct B(f32);
9+
#[derive(Component)]
10+
#[storage(VecStorage)]
11+
struct C(f32);
12+
#[derive(Component)]
13+
#[storage(VecStorage)]
14+
struct D(f32);
15+
#[derive(Component)]
16+
#[storage(VecStorage)]
17+
struct E(f32);
18+
19+
struct ABSystem;
20+
21+
impl<'a> System<'a> for ABSystem {
22+
type SystemData = (WriteStorage<'a, A>, WriteStorage<'a, B>);
23+
24+
fn run(&mut self, (mut a_store, mut b_store): Self::SystemData) {
25+
for (a, b) in (&mut a_store, &mut b_store).join() {
26+
std::mem::swap(&mut a.0, &mut b.0);
27+
}
28+
}
29+
}
30+
31+
struct CDSystem;
32+
33+
impl<'a> System<'a> for CDSystem {
34+
type SystemData = (WriteStorage<'a, C>, WriteStorage<'a, D>);
35+
36+
fn run(&mut self, (mut c_store, mut d_store): Self::SystemData) {
37+
for (c, d) in (&mut c_store, &mut d_store).join() {
38+
std::mem::swap(&mut c.0, &mut d.0);
39+
}
40+
}
41+
}
42+
struct CESystem;
43+
44+
impl<'a> System<'a> for CESystem {
45+
type SystemData = (WriteStorage<'a, C>, WriteStorage<'a, E>);
46+
47+
fn run(&mut self, (mut c_store, mut e_store): Self::SystemData) {
48+
for (c, e) in (&mut c_store, &mut e_store).join() {
49+
std::mem::swap(&mut c.0, &mut e.0);
50+
}
51+
}
52+
}
53+
54+
pub struct Benchmark<'a>(World, Dispatcher<'a, 'a>);
55+
56+
impl Benchmark<'_> {
57+
pub fn new() -> Self {
58+
let mut world = World::new();
59+
world.register::<A>();
60+
world.register::<B>();
61+
world.register::<C>();
62+
world.register::<D>();
63+
world.register::<E>();
64+
(0..10000).for_each(|_| {
65+
world.create_entity().with(A(0.0)).build();
66+
});
67+
(0..10000).for_each(|_| {
68+
world.create_entity().with(A(0.0)).with(B(0.0)).build();
69+
});
70+
(0..10000).for_each(|_| {
71+
world
72+
.create_entity()
73+
.with(A(0.0))
74+
.with(B(0.0))
75+
.with(C(0.0))
76+
.build();
77+
});
78+
(0..10000).for_each(|_| {
79+
world
80+
.create_entity()
81+
.with(A(0.0))
82+
.with(B(0.0))
83+
.with(C(0.0))
84+
.with(D(0.0))
85+
.build();
86+
});
87+
(0..10000).for_each(|_| {
88+
world
89+
.create_entity()
90+
.with(A(0.0))
91+
.with(B(0.0))
92+
.with(C(0.0))
93+
.with(E(0.0))
94+
.build();
95+
});
96+
97+
let dispatcher = DispatcherBuilder::new()
98+
.with(ABSystem, "ab", &[])
99+
.with(CDSystem, "cd", &[])
100+
.with(CESystem, "ce", &[])
101+
.build();
102+
103+
Self(world, dispatcher)
104+
}
105+
106+
pub fn run(&mut self) {
107+
self.1.dispatch_par(&self.0)
108+
}
109+
}

src/specs/simple_insert.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
use cgmath::*;
2+
use specs::prelude::*;
3+
use specs_derive::*;
4+
5+
#[derive(Copy, Clone, Component)]
6+
#[storage(VecStorage)]
7+
struct Transform(Matrix4<f32>);
8+
#[derive(Copy, Clone, Component)]
9+
#[storage(VecStorage)]
10+
struct Position(Vector3<f32>);
11+
12+
#[derive(Copy, Clone, Component)]
13+
#[storage(VecStorage)]
14+
struct Rotation(Vector3<f32>);
15+
16+
#[derive(Copy, Clone, Component)]
17+
#[storage(VecStorage)]
18+
struct Velocity(Vector3<f32>);
19+
20+
pub struct Benchmark;
21+
22+
impl Benchmark {
23+
pub fn new() -> Self {
24+
Self
25+
}
26+
27+
pub fn run(&mut self) {
28+
let mut world = World::new();
29+
world.register::<Transform>();
30+
world.register::<Position>();
31+
world.register::<Rotation>();
32+
world.register::<Velocity>();
33+
(0..10000).for_each(|_| {
34+
world
35+
.create_entity()
36+
.with(Transform(Matrix4::<f32>::from_scale(1.0)))
37+
.with(Position(Vector3::unit_x()))
38+
.with(Rotation(Vector3::unit_x()))
39+
.with(Velocity(Vector3::unit_x()))
40+
.build();
41+
});
42+
}
43+
}

0 commit comments

Comments
 (0)