|
- use std::io::Error as IoError;
- use std::time::{Duration, Instant};
-
- use async_ecs::{
- dispatcher::Error as DispatcherError, AsyncSystem, Dispatcher, Join, ParJoin, ParallelIterator,
- ReadStorage, System, VecStorage, World, WriteStorage,
- };
- use async_ecs_derive::Component;
- use log::info;
- use rand::random;
- use thiserror::Error;
- use tokio::{runtime::Builder, task::LocalSet};
-
- fn main() -> Result<(), Error> {
- env_logger::builder()
- .filter_level(log::LevelFilter::Info)
- .format_timestamp_nanos()
- .init();
-
- let rt = Builder::new_multi_thread()
- .worker_threads(num_cpus::get() + 4)
- .enable_all()
- .build()?;
-
- rt.block_on(async move { LocalSet::new().run_until(run()).await })
- }
-
- async fn run() -> Result<(), Error> {
- info!("Application started!");
- info!(" num_cpus = {}", num_cpus::get());
-
- let mut world = World::default();
- world.register_component::<Position>();
- world.register_component::<Velocity>();
- world.register_component::<Acceleration>();
-
- for _ in 0..ENTITY_COUNT {
- world
- .create_entity()
- .with(Velocity::random())
- .with(Position::random())
- .with(Acceleration::random())
- .build();
- }
-
- info!("World initialized!");
-
- let mut dispatcher = Dispatcher::builder()
- .with(ParMove, "move", &[])?
- .with(ParAccelerate, "accelerate", &["move"])?
- .build();
-
- info!("Setup done!");
-
- let mut delta = Duration::from_secs(0);
- for _ in 0..REPEAT_COUNT {
- info!("Start iteration");
-
- let start = Instant::now();
-
- world = dispatcher.dispatch(world).await?;
-
- let end = Instant::now();
-
- info!("End iteration");
-
- delta += end - start;
- }
-
- let delta = delta / REPEAT_COUNT;
-
- info!("Average time per dispatch: {:?}", delta);
-
- Ok(())
- }
-
- const ENTITY_COUNT: usize = 1_000_000;
- const REPEAT_COUNT: u32 = 100;
-
- #[derive(Debug, Component)]
- #[storage(VecStorage)]
- struct Position {
- x: f64,
- y: f64,
- }
-
- #[derive(Debug, Component)]
- #[storage(VecStorage)]
- struct Velocity {
- x: f64,
- y: f64,
- }
-
- #[derive(Debug, Component)]
- #[storage(VecStorage)]
- struct Acceleration {
- x: f64,
- y: f64,
- }
-
- struct SeqMove;
- struct SeqAccelerate;
-
- struct ParMove;
- struct ParAccelerate;
-
- #[derive(Debug, Error)]
- enum Error {
- #[error("IO Error: {0}")]
- IoError(IoError),
-
- #[error("Dispatcher Error: {0}")]
- DispatcherError(DispatcherError),
- }
-
- impl Position {
- fn random() -> Self {
- Self {
- x: random::<f64>() - 0.5,
- y: random::<f64>() - 0.5,
- }
- }
- }
-
- impl Velocity {
- fn random() -> Self {
- Self {
- x: random::<f64>() - 0.5,
- y: random::<f64>() - 0.5,
- }
- }
- }
-
- impl Acceleration {
- fn random() -> Self {
- Self {
- x: random::<f64>() - 0.5,
- y: random::<f64>() - 0.5,
- }
- }
- }
-
- impl<'a> System<'a> for SeqMove {
- type SystemData = (WriteStorage<'a, Position>, ReadStorage<'a, Velocity>);
-
- fn run(&mut self, (mut position, velocity): Self::SystemData) {
- for (position, velocity) in (&mut position, &velocity).join() {
- position.x += velocity.x;
- position.y += velocity.y;
- }
- }
- }
-
- impl<'a> AsyncSystem<'a> for SeqAccelerate {
- type SystemData = (WriteStorage<'a, Velocity>, ReadStorage<'a, Acceleration>);
- type Future = futures::future::Ready<()>;
-
- fn run(&mut self, (mut velocity, acceleration): Self::SystemData) -> Self::Future {
- for (velocity, acceleration) in (&mut velocity, &acceleration).join() {
- velocity.x += acceleration.x;
- velocity.y += acceleration.y;
- }
-
- futures::future::ready(())
- }
- }
-
- impl<'a> System<'a> for ParMove {
- type SystemData = (WriteStorage<'a, Position>, ReadStorage<'a, Velocity>);
-
- fn run(&mut self, (mut position, velocity): Self::SystemData) {
- (&mut position, &velocity)
- .par_join()
- .for_each(|(position, velocity)| {
- position.x += velocity.x;
- position.y += velocity.y;
- });
- }
- }
-
- impl<'a> AsyncSystem<'a> for ParAccelerate {
- type SystemData = (WriteStorage<'a, Velocity>, ReadStorage<'a, Acceleration>);
- type Future = futures::future::Ready<()>;
-
- fn run(&mut self, (mut velocity, acceleration): Self::SystemData) -> Self::Future {
- (&mut velocity, &acceleration)
- .par_join()
- .for_each(|(velocity, acceleration)| {
- velocity.x += acceleration.x;
- velocity.y += acceleration.y;
- });
-
- futures::future::ready(())
- }
- }
-
- impl From<IoError> for Error {
- fn from(err: IoError) -> Self {
- Self::IoError(err)
- }
- }
-
- impl From<DispatcherError> for Error {
- fn from(err: DispatcherError) -> Self {
- Self::DispatcherError(err)
- }
- }
|