use criterion::*; use geese::*; use std::marker::*; use std::ops::*; use std::sync::atomic::*; use std::sync::*; fn fibonacci(n: u64) -> u64 { match n { 0 => 1, 1 => 1, n => fibonacci(n - 1) + fibonacci(n - 2), } } struct SpinSystem { ctx: GeeseContextHandle, on_spin: Option>, data: PhantomData, } impl SpinSystem { fn spin(&mut self, value: &C) { if value.is_nonzero() { self.ctx.raise_event(value.decrement()); if let Some(spin) = &self.on_spin { spin(); } } } } impl GeeseSystem for SpinSystem { const EVENT_HANDLERS: EventHandlers = event_handlers().with(Self::spin); fn new(ctx: GeeseContextHandle) -> Self { Self { ctx, data: PhantomData, on_spin: None, } } } struct OldSpinSystem { ctx: old_geese::GeeseContextHandle, on_spin: Option>, data: PhantomData, } impl OldSpinSystem { fn spin(&mut self, value: &C) { if value.is_nonzero() { self.ctx.raise_event(value.decrement()); if let Some(spin) = &self.on_spin { spin(); } } } } impl old_geese::GeeseSystem for OldSpinSystem { fn new(ctx: old_geese::GeeseContextHandle) -> Self { Self { ctx, data: PhantomData, on_spin: None, } } fn register(with: &mut old_geese::GeeseSystemData) { with.event(Self::spin); } } fn bench_spin(c: &mut Criterion) { let mut old_ctx = old_geese::GeeseContext::default(); old_ctx.raise_event(old_geese::notify::add_system::>()); old_ctx.flush_events(); c.bench_function("old_spin", |b| { b.iter(|| { old_ctx.raise_event(1000usize); old_ctx.flush_events(); }) }); let mut ctx = GeeseContext::default(); ctx.raise_event(geese::notify::add_system::>()); ctx.flush_events(); c.bench_function("new_spin", |b| { b.iter(|| { ctx.raise_event(1000usize); ctx.flush_events(); }) }); } fn bench_double(c: &mut Criterion) { let mut old_ctx = old_geese::GeeseContext::default(); old_ctx.raise_event(old_geese::notify::add_system::>()); old_ctx.raise_event(old_geese::notify::add_system::>()); old_ctx.flush_events(); c.bench_function("double_old", |b| { b.iter(|| { old_ctx.raise_event(1000usize); old_ctx.raise_event(1000isize); old_ctx.flush_events(); }) }); let mut ctx = GeeseContext::default(); ctx.raise_event(geese::notify::add_system::>()); ctx.raise_event(geese::notify::add_system::>()); ctx.flush_events(); c.bench_function("double_new", |b| { b.iter(|| { ctx.raise_event(1000usize); ctx.raise_event(1000isize); ctx.flush_events(); }) }); ctx.set_threadpool(HardwareThreadPool::new(1)); c.bench_function("double_new_multi", |b| { b.iter(|| { ctx.raise_event(1000usize); ctx.raise_event(1000isize); ctx.flush_events(); }) }); } fn bench_double_work(c: &mut Criterion) { let work = Arc::new(|| { black_box(fibonacci(black_box(18))); }); let mut old_ctx = old_geese::GeeseContext::default(); old_ctx.raise_event(old_geese::notify::add_system::>()); old_ctx.raise_event(old_geese::notify::add_system::>()); old_ctx.flush_events(); old_ctx.system_mut::>().on_spin = Some(work.clone()); old_ctx.system_mut::>().on_spin = Some(work.clone()); c.bench_function("work_old_double", |b| { b.iter(|| { old_ctx.raise_event(1000usize); old_ctx.raise_event(1000isize); old_ctx.flush_events(); }) }); let mut ctx = GeeseContext::default(); ctx.raise_event(geese::notify::add_system::>()); ctx.raise_event(geese::notify::add_system::>()); ctx.flush_events(); ctx.system_mut::>().on_spin = Some(work.clone()); ctx.system_mut::>().on_spin = Some(work.clone()); c.bench_function("work_new_double", |b| { b.iter(|| { ctx.raise_event(1000usize); ctx.raise_event(1000isize); ctx.flush_events(); }) }); ctx.set_threadpool(HardwareThreadPool::new(1)); c.bench_function("work_new_multi", |b| { b.iter(|| { ctx.raise_event(1000usize); ctx.raise_event(1000isize); ctx.flush_events(); }) }); } trait Counter: 'static + Copy + Send + Sync + Sized { fn decrement(self) -> Self; fn is_nonzero(self) -> bool; } impl Counter for isize { fn decrement(self) -> Self { self - 1 } fn is_nonzero(self) -> bool { self != 0 } } impl Counter for usize { fn decrement(self) -> Self { self - 1 } fn is_nonzero(self) -> bool { self != 0 } } struct TestDependency { ctx: GeeseContextHandle, } impl TestDependency { fn get_it(&mut self, event: &()) { for i in 0..1000 { self.ctx.get::().test(); } } } impl GeeseSystem for TestDependency { const DEPENDENCIES: Dependencies = dependencies().with::(); const EVENT_HANDLERS: EventHandlers = event_handlers().with(Self::get_it); fn new(ctx: GeeseContextHandle) -> Self { Self { ctx } } } struct TestDependencyOld { ctx: old_geese::GeeseContextHandle, } impl TestDependencyOld { fn get_it(&mut self, event: &()) { for i in 0..1000 { self.ctx.system::().test(); } } } impl old_geese::GeeseSystem for TestDependencyOld { fn new(ctx: old_geese::GeeseContextHandle) -> Self { Self { ctx } } fn register(with: &mut old_geese::GeeseSystemData) { with.dependency::(); with.event(Self::get_it); } } struct TestDependent; impl TestDependent { pub fn test(&self) { black_box(self); } } impl GeeseSystem for TestDependent { fn new(_: GeeseContextHandle) -> Self { Self } } impl old_geese::GeeseSystem for TestDependent { fn new(_: old_geese::GeeseContextHandle) -> Self { Self } } fn bench_dep_fetch(c: &mut Criterion) { let mut old_ctx = old_geese::GeeseContext::default(); old_ctx.raise_event(old_geese::notify::add_system::()); old_ctx.flush_events(); c.bench_function("dep_fetch_old", |b| { b.iter(|| { old_ctx.raise_event(()); old_ctx.flush_events(); }) }); let mut ctx = GeeseContext::default(); ctx.raise_event(geese::notify::add_system::()); ctx.flush_events(); c.bench_function("dep_fetch_new", |b| { b.iter(|| { old_ctx.raise_event(()); ctx.flush_events(); }) }); } criterion_group!( benches, bench_spin, bench_double, bench_double_work, bench_dep_fetch ); criterion_main!(benches);