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

Add brood ECS. #29

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ edition = "2018"
bevy_ecs = "0.5.0"
bevy_tasks = "0.5.0"
bincode = "1.3"
brood = { version = "0.1.0", features = ["rayon", "serde"] }
cgmath = { version = "0.17", features = ["serde"] }
hecs = { version = "0.5", features = ["column-serialize", "row-serialize"] }
legion = "0.3"
Expand Down
32 changes: 32 additions & 0 deletions benches/benchmarks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ use ecs_bench_suite::*;

fn bench_simple_insert(c: &mut Criterion) {
let mut group = c.benchmark_group("simple_insert");
group.bench_function("brood", |b| {
let mut bench = brood::simple_insert::Benchmark::new();
b.iter(move || bench.run());
});
group.bench_function("legion", |b| {
let mut bench = legion::simple_insert::Benchmark::new();
b.iter(move || bench.run());
Expand Down Expand Up @@ -31,6 +35,10 @@ fn bench_simple_insert(c: &mut Criterion) {

fn bench_simple_iter(c: &mut Criterion) {
let mut group = c.benchmark_group("simple_iter");
group.bench_function("brood", |b| {
let mut bench = brood::simple_iter::Benchmark::new();
b.iter(move || bench.run());
});
group.bench_function("legion", |b| {
let mut bench = legion::simple_iter::Benchmark::new();
b.iter(move || bench.run());
Expand Down Expand Up @@ -63,6 +71,10 @@ fn bench_simple_iter(c: &mut Criterion) {

fn bench_frag_iter_bc(c: &mut Criterion) {
let mut group = c.benchmark_group("fragmented_iter");
group.bench_function("brood", |b| {
let mut bench = brood::frag_iter::Benchmark::new();
b.iter(move || bench.run());
});
group.bench_function("legion", |b| {
let mut bench = legion::frag_iter::Benchmark::new();
b.iter(move || bench.run());
Expand Down Expand Up @@ -91,6 +103,10 @@ fn bench_frag_iter_bc(c: &mut Criterion) {

fn bench_schedule(c: &mut Criterion) {
let mut group = c.benchmark_group("schedule");
group.bench_function("brood", |b| {
let mut bench = brood::schedule::Benchmark::new();
b.iter(move || bench.run());
});
group.bench_function("legion", |b| {
let mut bench = legion::schedule::Benchmark::new();
b.iter(move || bench.run());
Expand Down Expand Up @@ -119,6 +135,10 @@ fn bench_schedule(c: &mut Criterion) {

fn bench_heavy_compute(c: &mut Criterion) {
let mut group = c.benchmark_group("heavy_compute");
group.bench_function("brood", |b| {
let mut bench = brood::heavy_compute::Benchmark::new();
b.iter(move || bench.run());
});
group.bench_function("legion", |b| {
let mut bench = legion::heavy_compute::Benchmark::new();
b.iter(move || bench.run());
Expand Down Expand Up @@ -147,6 +167,10 @@ fn bench_heavy_compute(c: &mut Criterion) {

fn bench_add_remove(c: &mut Criterion) {
let mut group = c.benchmark_group("add_remove_component");
group.bench_function("brood", |b| {
let mut bench = brood::add_remove::Benchmark::new();
b.iter(move || bench.run());
});
group.bench_function("legion", |b| {
let mut bench = legion::add_remove::Benchmark::new();
b.iter(move || bench.run());
Expand Down Expand Up @@ -175,6 +199,10 @@ fn bench_add_remove(c: &mut Criterion) {

fn bench_serialize_text(c: &mut Criterion) {
let mut group = c.benchmark_group("serialize_text");
group.bench_function("brood", |b| {
let mut bench = brood::serialize_text::Benchmark::new();
b.iter(move || bench.run());
});
group.bench_function("legion", |b| {
let mut bench = legion::serialize_text::Benchmark::new();
b.iter(move || bench.run());
Expand All @@ -191,6 +219,10 @@ fn bench_serialize_text(c: &mut Criterion) {

fn bench_serialize_binary(c: &mut Criterion) {
let mut group = c.benchmark_group("serialize_binary");
group.bench_function("brood", |b| {
let mut bench = brood::serialize_binary::Benchmark::new();
b.iter(move || bench.run());
});
group.bench_function("legion", |b| {
let mut bench = legion::serialize_binary::Benchmark::new();
b.iter(move || bench.run());
Expand Down
29 changes: 29 additions & 0 deletions src/brood/add_remove.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use brood::{entities, entity, registry, World};

#[derive(Clone)]
struct A(f32);
struct B(f32);

type Registry = registry!(A, B);

pub struct Benchmark(World<Registry>, Vec<entity::Identifier>);

impl Benchmark {
pub fn new() -> Self {
let mut world = World::new();

let entities = world.extend(entities!((A(0.0)); 10_000));

Self(world, entities)
}

pub fn run(&mut self) {
for entity_identifier in &self.1 {
self.0.entry(*entity_identifier).unwrap().add(B(0.0));
}

for entity_identifier in &self.1 {
self.0.entry(*entity_identifier).unwrap().remove::<B>();
}
}
}
47 changes: 47 additions & 0 deletions src/brood/frag_iter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use brood::{
entities,
query::{filter, result, views},
registry, World,
};

macro_rules! define_entities {
($($component:ident),*) => {
$(
#[derive(Clone)]
struct $component(f32);
)*
}
}

macro_rules! create_entities {
($world:ident; $($component:ident),*) => {
$(
$world.extend(entities!(($component(0.0), Data(1.0)); 20));
)*
};
}

#[derive(Clone)]
struct Data(f32);
define_entities!(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);

type Registry =
registry!(Data, 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);

pub struct Benchmark(World<Registry>);

impl Benchmark {
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);

Self(world)
}

pub fn run(&mut self) {
for result!(data) in self.0.query::<views!(&mut Data), filter::None>() {
data.0 *= 2.0;
}
}
}
46 changes: 46 additions & 0 deletions src/brood/heavy_compute.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use brood::{
entities,
query::{filter, result, views},
registry, World,
};
use cgmath::{Matrix4, Rad, SquareMatrix, Transform, Vector3};
use rayon::iter::ParallelIterator;

#[derive(Copy, Clone)]
struct Position(Vector3<f32>);

#[derive(Copy, Clone)]
struct Rotation(Vector3<f32>);

#[derive(Copy, Clone)]
struct Velocity(Vector3<f32>);

type Registry = registry!(Position, Rotation, Velocity, Matrix4<f32>);

pub struct Benchmark(World<Registry>);

impl Benchmark {
pub fn new() -> Self {
let mut world = World::new();

world.extend(entities!((
Matrix4::<f32>::from_angle_x(Rad(1.2)),
Position(Vector3::unit_x()),
Rotation(Vector3::unit_x()),
Velocity(Vector3::unit_x())
); 1_000));

Self(world)
}

pub fn run(&mut self) {
self.0
.par_query::<views!(&mut Position, &mut Matrix4<f32>), filter::None>()
.for_each(|result!(position, matrix)| {
for _ in 0..100 {
*matrix = matrix.invert().unwrap();
}
position.0 = matrix.transform_vector(position.0);
});
}
}
8 changes: 8 additions & 0 deletions src/brood/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
pub mod add_remove;
pub mod frag_iter;
pub mod heavy_compute;
pub mod schedule;
pub mod serialize_binary;
pub mod serialize_text;
pub mod simple_insert;
pub mod simple_iter;
98 changes: 98 additions & 0 deletions src/brood/schedule.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
use brood::{
entities,
query::{filter, result, views},
registry,
system::{schedule, Schedule, System},
World,
};

#[derive(Clone)]
struct A(f32);
#[derive(Clone)]
struct B(f32);
#[derive(Clone)]
struct C(f32);
#[derive(Clone)]
struct D(f32);
#[derive(Clone)]
struct E(f32);

type Registry = registry!(A, B, C, D, E);

struct AB;

impl<'a> System<'a> for AB {
type Views = views!(&'a mut A, &'a mut B);
type Filter = filter::None;

fn run<R>(&mut self, query_results: result::Iter<'a, R, Self::Filter, Self::Views>)
where
R: brood::registry::Registry + 'a,
{
for result!(a, b) in query_results {
std::mem::swap(&mut a.0, &mut b.0);
}
}
}

struct CD;

impl<'a> System<'a> for CD {
type Views = views!(&'a mut C, &'a mut D);
type Filter = filter::None;

fn run<R>(&mut self, query_results: result::Iter<'a, R, Self::Filter, Self::Views>)
where
R: brood::registry::Registry + 'a,
{
for result!(c, d) in query_results {
std::mem::swap(&mut c.0, &mut d.0);
}
}
}

struct CE;

impl<'a> System<'a> for CE {
type Views = views!(&'a mut C, &'a mut E);
type Filter = filter::None;

fn run<R>(&mut self, query_results: result::Iter<'a, R, Self::Filter, Self::Views>)
where
R: brood::registry::Registry + 'a,
{
for result!(c, e) in query_results {
std::mem::swap(&mut c.0, &mut e.0);
}
}
}

pub struct Benchmark(
World<Registry>,
Schedule<
schedule::stages! {
system: AB,
system: CD,
system: CE,
},
>,
);

impl Benchmark {
pub fn new() -> Self {
let mut world = World::new();

world.extend(entities!((A(0.0), B(0.0)); 10_000));
world.extend(entities!((A(0.0), B(0.0), C(0.0)); 10_000));
world.extend(entities!((A(0.0), B(0.0), C(0.0), D(0.0)); 10_000));
world.extend(entities!((A(0.0), B(0.0), C(0.0), E(0.0)); 10_000));

let schedule = Schedule::builder().system(AB).system(CD).system(CE).build();

Self(world, schedule)
}

pub fn run(&mut self) {
self.0.run_schedule(&mut self.1);
}
}
45 changes: 45 additions & 0 deletions src/brood/serialize_binary.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use brood::{entities, registry, World};
use serde::{Deserialize, Serialize};

#[derive(Default, Copy, Clone, Serialize, Deserialize)]
struct Transform([f32; 16]);

#[derive(Default, Copy, Clone, Serialize, Deserialize)]
struct Position {
x: f32,
y: f32,
z: f32,
}

#[derive(Default, Copy, Clone, Serialize, Deserialize)]
struct Rotation {
x: f32,
y: f32,
z: f32,
}

#[derive(Default, Copy, Clone, Serialize, Deserialize)]
struct Velocity {
x: f32,
y: f32,
z: f32,
}

type Registry = registry!(Transform, Position, Rotation, Velocity);

pub struct Benchmark(World<Registry>);

impl Benchmark {
pub fn new() -> Self {
let mut world = World::default();

world.extend(entities!((Transform::default(), Position::default(), Rotation::default(), Velocity::default()); 1_000));

Self(world)
}

pub fn run(&mut self) {
let encoded = bincode::serialize(&self.0).unwrap();
bincode::deserialize::<World<Registry>>(&encoded).unwrap();
}
}
Loading