-
-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Parallel event reader #12554
Parallel event reader #12554
Conversation
Implement `EventReader::par_read()` returning `EventParIter`. Currently the only operator implemented is `for_each`.
/// ``` | ||
/// # use bevy_ecs::prelude::*; | ||
/// # use std::sync::atomic::{AtomicUsize, Ordering}; | ||
/// | ||
/// #[derive(Event)] | ||
/// struct MyEvent { | ||
/// value: usize, | ||
/// } | ||
/// | ||
/// #[derive(Resource, Default)] | ||
/// struct Counter(AtomicUsize); | ||
/// | ||
/// // setup | ||
/// let mut world = World::new(); | ||
/// world.init_resource::<Events<MyEvent>>(); | ||
/// world.insert_resource(Counter::default()); | ||
/// | ||
/// let mut schedule = Schedule::default(); | ||
/// schedule.add_systems(|mut events: EventReader<MyEvent>, counter: Res<Counter>| { | ||
/// events.par_read().for_each(|MyEvent { value }| { | ||
/// counter.0.fetch_add(*value, Ordering::Relaxed); | ||
/// }); | ||
/// }); | ||
/// for value in 0..100 { | ||
/// world.send_event(MyEvent { value }); | ||
/// } | ||
/// schedule.run(&mut world); | ||
/// let Counter(counter) = world.remove_resource::<Counter>().unwrap(); | ||
/// // all events were processed | ||
/// assert_eq!(counter.into_inner(), 4950); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The example is a bit contrived
f818e29
to
9ae50b4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is a good API surface. Ideally we wouldn't need to be manually batching, and employ something similar to Rayon's workstealing in more flexible slices, but that may be a while before we can tackle something like that.
Also document that event IDs are increasing by send order. This is already implied due to the `Ord` trait impl.
Encapsulate the batch size calculation logic in `BatchingStrategy`
e890449
to
843aecf
Compare
Co-authored-by: James Liu <contact@jamessliu.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just some comments in docs, otherwise, all good.
Co-authored-by: Pablo Reinhardt <126117294+pablo-lua@users.noreply.github.com>
Objective
Allow parallel iteration over events, resolve #10766
Solution
EventParIter
which works similarly toQueryParIter
, implementing afor_each{_with_id}
operator.I chose to not mirror
EventIteratorWithId
and instead implement both operations on a single struct.BatchingStrategy
fromQueryParIter
Changelog
EventReader
now supports parallel event iteration usingpar_read().for_each(|event| ...)
.