mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
Only run event systems if they have tangible work to do (#7728)
# Objective Scheduling low cost systems has significant overhead due to task pool contention and the extra machinery to schedule and run them. Event update systems are the prime example of a low cost system, requiring a guaranteed O(1) operation, and there are a *lot* of them. ## Solution Add a run condition to every event system so they only run when there is an event in either of it's two internal Vecs. --- ## Changelog Changed: Event update systems will not run if there are no events to process. ## Migration Guide `Events<T>::update_system` has been split off from the the type and can be found at `bevy_ecs::event::event_update_system`. --------- Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
This commit is contained in:
parent
22dfa9ee96
commit
8ace2ff9e3
4 changed files with 22 additions and 11 deletions
|
@ -424,7 +424,7 @@ impl App {
|
|||
/// Setup the application to manage events of type `T`.
|
||||
///
|
||||
/// This is done by adding a [`Resource`] of type [`Events::<T>`],
|
||||
/// and inserting an [`update_system`](Events::update_system) into [`First`].
|
||||
/// and inserting an [`event_update_system`] into [`First`].
|
||||
///
|
||||
/// See [`Events`] for defining events.
|
||||
///
|
||||
|
@ -440,13 +440,18 @@ impl App {
|
|||
/// #
|
||||
/// app.add_event::<MyEvent>();
|
||||
/// ```
|
||||
///
|
||||
/// [`event_update_system`]: bevy_ecs::event::event_update_system
|
||||
pub fn add_event<T>(&mut self) -> &mut Self
|
||||
where
|
||||
T: Event,
|
||||
{
|
||||
if !self.world.contains_resource::<Events<T>>() {
|
||||
self.init_resource::<Events<T>>()
|
||||
.add_systems(First, Events::<T>::update_system);
|
||||
self.init_resource::<Events<T>>().add_systems(
|
||||
First,
|
||||
bevy_ecs::event::event_update_system::<T>
|
||||
.run_if(bevy_ecs::event::event_update_condition::<T>),
|
||||
);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ fn main() {
|
|||
#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct FlushEvents;
|
||||
|
||||
schedule.add_systems(Events::<MyEvent>::update_system.in_set(FlushEvents));
|
||||
schedule.add_systems(bevy_ecs::event::event_update_system::<MyEvent>.in_set(FlushEvents));
|
||||
|
||||
// Add systems sending and receiving events after the events are flushed.
|
||||
schedule.add_systems((
|
||||
|
|
|
@ -103,7 +103,7 @@ struct EventInstance<E: Event> {
|
|||
/// This collection is meant to be paired with a system that calls
|
||||
/// [`Events::update`] exactly once per update/frame.
|
||||
///
|
||||
/// [`Events::update_system`] is a system that does this, typically initialized automatically using
|
||||
/// [`event_update_system`] is a system that does this, typically initialized automatically using
|
||||
/// [`add_event`](https://docs.rs/bevy/*/bevy/app/struct.App.html#method.add_event).
|
||||
/// [`EventReader`]s are expected to read events from this collection at least once per loop/frame.
|
||||
/// Events will persist across a single frame boundary and so ordering of event producers and
|
||||
|
@ -251,11 +251,6 @@ impl<E: Event> Events<E> {
|
|||
iter.map(|e| e.event)
|
||||
}
|
||||
|
||||
/// A system that calls [`Events::update`] once per frame.
|
||||
pub fn update_system(mut events: ResMut<Self>) {
|
||||
events.update();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn reset_start_event_count(&mut self) {
|
||||
self.events_a.start_event_count = self.event_count;
|
||||
|
@ -754,6 +749,17 @@ impl<'a, E: Event> ExactSizeIterator for EventIteratorWithId<'a, E> {
|
|||
}
|
||||
}
|
||||
|
||||
/// A system that calls [`Events::update`] once per frame.
|
||||
pub fn event_update_system<T: Event>(mut events: ResMut<Events<T>>) {
|
||||
events.update();
|
||||
}
|
||||
|
||||
/// A run condition that checks if the event's [`event_update_system`]
|
||||
/// needs to run or not.
|
||||
pub fn event_update_condition<T: Event>(events: Res<Events<T>>) -> bool {
|
||||
!events.events_a.is_empty() || !events.events_b.is_empty()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::system::assert_is_read_only_system;
|
||||
|
|
|
@ -867,7 +867,7 @@ pub mod common_conditions {
|
|||
/// # let mut world = World::new();
|
||||
/// # world.init_resource::<Counter>();
|
||||
/// # world.init_resource::<Events<MyEvent>>();
|
||||
/// # app.add_systems(Events::<MyEvent>::update_system.before(my_system));
|
||||
/// # app.add_systems(bevy_ecs::event::event_update_system::<MyEvent>.before(my_system));
|
||||
///
|
||||
/// app.add_systems(
|
||||
/// my_system.run_if(on_event::<MyEvent>()),
|
||||
|
|
Loading…
Reference in a new issue