diff --git a/benches/benches/bevy_ecs/scheduling/mod.rs b/benches/benches/bevy_ecs/scheduling/mod.rs index 2d0529696b9ad9..60d1620a89f5c1 100644 --- a/benches/benches/bevy_ecs/scheduling/mod.rs +++ b/benches/benches/bevy_ecs/scheduling/mod.rs @@ -19,4 +19,5 @@ criterion_group!( contrived, schedule, build_schedule, + empty_schedule_run, ); diff --git a/benches/benches/bevy_ecs/scheduling/schedule.rs b/benches/benches/bevy_ecs/scheduling/schedule.rs index a45db34c4368f1..dc7068325e6ca9 100644 --- a/benches/benches/bevy_ecs/scheduling/schedule.rs +++ b/benches/benches/bevy_ecs/scheduling/schedule.rs @@ -118,3 +118,28 @@ pub fn build_schedule(criterion: &mut Criterion) { group.finish(); } + +pub fn empty_schedule_run(criterion: &mut Criterion) { + let mut app = bevy_app::App::default(); + + let mut group = criterion.benchmark_group("run_empty_schedule"); + + let mut schedule = Schedule::default(); + schedule.set_executor_kind(bevy_ecs::schedule::ExecutorKind::SingleThreaded); + group.bench_function("SingleThreaded", |bencher| { + bencher.iter(|| schedule.run(&mut app.world)); + }); + + let mut schedule = Schedule::default(); + schedule.set_executor_kind(bevy_ecs::schedule::ExecutorKind::MultiThreaded); + group.bench_function("MultiThreaded", |bencher| { + bencher.iter(|| schedule.run(&mut app.world)); + }); + + let mut schedule = Schedule::default(); + schedule.set_executor_kind(bevy_ecs::schedule::ExecutorKind::Simple); + group.bench_function("Simple", |bencher| { + bencher.iter(|| schedule.run(&mut app.world)); + }); + group.finish(); +} diff --git a/crates/bevy_ecs/src/schedule/executor/mod.rs b/crates/bevy_ecs/src/schedule/executor/mod.rs index fdc11fe326c472..b293506342cccb 100644 --- a/crates/bevy_ecs/src/schedule/executor/mod.rs +++ b/crates/bevy_ecs/src/schedule/executor/mod.rs @@ -21,8 +21,8 @@ pub(super) trait SystemExecutor: Send + Sync { fn run( &mut self, schedule: &mut SystemSchedule, - skip_systems: Option, world: &mut World, + skip_systems: Option<&FixedBitSet>, ); fn set_apply_final_deferred(&mut self, value: bool); } diff --git a/crates/bevy_ecs/src/schedule/executor/multi_threaded.rs b/crates/bevy_ecs/src/schedule/executor/multi_threaded.rs index 90471c5978b19f..c17c1dbd73a065 100644 --- a/crates/bevy_ecs/src/schedule/executor/multi_threaded.rs +++ b/crates/bevy_ecs/src/schedule/executor/multi_threaded.rs @@ -166,8 +166,8 @@ impl SystemExecutor for MultiThreadedExecutor { fn run( &mut self, schedule: &mut SystemSchedule, - _skip_systems: Option, world: &mut World, + _skip_systems: Option<&FixedBitSet>, ) { // reset counts self.num_systems = schedule.systems.len(); @@ -189,26 +189,18 @@ impl SystemExecutor for MultiThreadedExecutor { // If stepping is enabled, make sure we skip those systems that should // not be run. #[cfg(feature = "bevy_debug_stepping")] - if let Some(mut skipped_systems) = _skip_systems { + if let Some(skipped_systems) = _skip_systems { debug_assert_eq!(skipped_systems.len(), self.completed_systems.len()); // mark skipped systems as completed - self.completed_systems |= &skipped_systems; + self.completed_systems |= skipped_systems; self.num_completed_systems = self.completed_systems.count_ones(..); // signal the dependencies for each of the skipped systems, as // though they had run for system_index in skipped_systems.ones() { self.signal_dependents(system_index); + self.ready_systems.set(system_index, false); } - - // Finally, we need to clear all skipped systems from the ready - // list. - // - // We invert the skipped system mask to get the list of systems - // that should be run. Then we bitwise AND it with the ready list, - // resulting in a list of ready systems that aren't skipped. - skipped_systems.toggle_range(..); - self.ready_systems &= skipped_systems; } let thread_executor = world diff --git a/crates/bevy_ecs/src/schedule/executor/simple.rs b/crates/bevy_ecs/src/schedule/executor/simple.rs index 28b1fb7141f85b..002ba532ad74b8 100644 --- a/crates/bevy_ecs/src/schedule/executor/simple.rs +++ b/crates/bevy_ecs/src/schedule/executor/simple.rs @@ -33,15 +33,15 @@ impl SystemExecutor for SimpleExecutor { fn run( &mut self, schedule: &mut SystemSchedule, - _skip_systems: Option, world: &mut World, + _skip_systems: Option<&FixedBitSet>, ) { // If stepping is enabled, make sure we skip those systems that should // not be run. #[cfg(feature = "bevy_debug_stepping")] if let Some(skipped_systems) = _skip_systems { // mark skipped systems as completed - self.completed_systems |= &skipped_systems; + self.completed_systems |= skipped_systems; } for system_index in 0..schedule.systems.len() { diff --git a/crates/bevy_ecs/src/schedule/executor/single_threaded.rs b/crates/bevy_ecs/src/schedule/executor/single_threaded.rs index 2bedc7bd74ad4a..502bed8af50e82 100644 --- a/crates/bevy_ecs/src/schedule/executor/single_threaded.rs +++ b/crates/bevy_ecs/src/schedule/executor/single_threaded.rs @@ -41,15 +41,15 @@ impl SystemExecutor for SingleThreadedExecutor { fn run( &mut self, schedule: &mut SystemSchedule, - _skip_systems: Option, world: &mut World, + _skip_systems: Option<&FixedBitSet>, ) { // If stepping is enabled, make sure we skip those systems that should // not be run. #[cfg(feature = "bevy_debug_stepping")] if let Some(skipped_systems) = _skip_systems { // mark skipped systems as completed - self.completed_systems |= &skipped_systems; + self.completed_systems |= skipped_systems; } for system_index in 0..schedule.systems.len() { diff --git a/crates/bevy_ecs/src/schedule/schedule.rs b/crates/bevy_ecs/src/schedule/schedule.rs index 512d1490693dac..200af2f5f594f2 100644 --- a/crates/bevy_ecs/src/schedule/schedule.rs +++ b/crates/bevy_ecs/src/schedule/schedule.rs @@ -333,15 +333,18 @@ impl Schedule { .unwrap_or_else(|e| panic!("Error when initializing schedule {:?}: {e}", self.label)); #[cfg(not(feature = "bevy_debug_stepping"))] - let skip_systems = None; + self.executor.run(&mut self.executable, world, None); #[cfg(feature = "bevy_debug_stepping")] - let skip_systems = match world.get_resource_mut::() { - None => None, - Some(mut stepping) => stepping.skipped_systems(self), - }; + { + let skip_systems = match world.get_resource_mut::() { + None => None, + Some(mut stepping) => stepping.skipped_systems(self), + }; - self.executor.run(&mut self.executable, skip_systems, world); + self.executor + .run(&mut self.executable, world, skip_systems.as_ref()); + } } /// Initializes any newly-added systems and conditions, rebuilds the executable schedule,