From af8d12c3e16ad50107c17f693daa7a36f4f409f6 Mon Sep 17 00:00:00 2001 From: Eagster <79881080+ElliottjPierce@users.noreply.github.com> Date: Mon, 5 May 2025 20:21:57 -0400 Subject: [PATCH] deprecate `SimpleExecutor` (#18753) # Objective Contributes to #18741 and #18453. ## Solution Deprecate `SimpleExecutor`. If users run into migration issues, we can backtrack. Otherwise, we follow this up with #18741 We can't easily deprecate the module too because of [this](https://github.com/rust-lang/rust/issues/47238). ## Testing CI --------- Co-authored-by: Alice Cecile Co-authored-by: Cyrill Schenkel --- .../benches/bevy_ecs/scheduling/schedule.rs | 1 + crates/bevy_ecs/src/schedule/executor/mod.rs | 7 ++++++ .../bevy_ecs/src/schedule/executor/simple.rs | 11 +++++++- crates/bevy_ecs/src/schedule/mod.rs | 1 + crates/bevy_ecs/src/schedule/schedule.rs | 1 + .../simple_executor_going_away.md | 25 +++++++++++++++++++ 6 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 release-content/migration-guides/simple_executor_going_away.md diff --git a/benches/benches/bevy_ecs/scheduling/schedule.rs b/benches/benches/bevy_ecs/scheduling/schedule.rs index 9844461d39..d7d1243f7f 100644 --- a/benches/benches/bevy_ecs/scheduling/schedule.rs +++ b/benches/benches/bevy_ecs/scheduling/schedule.rs @@ -137,6 +137,7 @@ pub fn empty_schedule_run(criterion: &mut Criterion) { }); let mut schedule = Schedule::default(); + #[expect(deprecated, reason = "We still need to test/bench this.")] schedule.set_executor_kind(bevy_ecs::schedule::ExecutorKind::Simple); group.bench_function("Simple", |bencher| { bencher.iter(|| schedule.run(app.world_mut())); diff --git a/crates/bevy_ecs/src/schedule/executor/mod.rs b/crates/bevy_ecs/src/schedule/executor/mod.rs index 2fc808bf28..4b3f9fdcef 100644 --- a/crates/bevy_ecs/src/schedule/executor/mod.rs +++ b/crates/bevy_ecs/src/schedule/executor/mod.rs @@ -6,6 +6,7 @@ mod single_threaded; use alloc::{borrow::Cow, vec, vec::Vec}; use core::any::TypeId; +#[expect(deprecated, reason = "We still need to support this.")] pub use self::{simple::SimpleExecutor, single_threaded::SingleThreadedExecutor}; #[cfg(feature = "std")] @@ -53,6 +54,10 @@ pub enum ExecutorKind { SingleThreaded, /// Like [`SingleThreaded`](ExecutorKind::SingleThreaded) but calls [`apply_deferred`](crate::system::System::apply_deferred) /// immediately after running each system. + #[deprecated( + since = "0.17.0", + note = "Use SingleThreaded instead. See https://github.com/bevyengine/bevy/issues/18453 for motivation." + )] Simple, /// Runs the schedule using a thread pool. Non-conflicting systems can run in parallel. #[cfg(feature = "std")] @@ -346,6 +351,7 @@ mod tests { struct TestComponent; const EXECUTORS: [ExecutorKind; 3] = [ + #[expect(deprecated, reason = "We still need to test this.")] ExecutorKind::Simple, ExecutorKind::SingleThreaded, ExecutorKind::MultiThreaded, @@ -406,6 +412,7 @@ mod tests { let mut world = World::new(); let mut schedule = Schedule::default(); + #[expect(deprecated, reason = "We still need to test this.")] schedule.set_executor_kind(ExecutorKind::Simple); schedule.add_systems(look_for_missing_resource); schedule.run(&mut world); diff --git a/crates/bevy_ecs/src/schedule/executor/simple.rs b/crates/bevy_ecs/src/schedule/executor/simple.rs index a237a356de..701a8d8f06 100644 --- a/crates/bevy_ecs/src/schedule/executor/simple.rs +++ b/crates/bevy_ecs/src/schedule/executor/simple.rs @@ -1,3 +1,5 @@ +#![expect(deprecated, reason = "Everything here is deprecated")] + use core::panic::AssertUnwindSafe; use fixedbitset::FixedBitSet; @@ -20,6 +22,10 @@ use super::__rust_begin_short_backtrace; /// A variant of [`SingleThreadedExecutor`](crate::schedule::SingleThreadedExecutor) that calls /// [`apply_deferred`](crate::system::System::apply_deferred) immediately after running each system. #[derive(Default)] +#[deprecated( + since = "0.17.0", + note = "Use SingleThreadedExecutor instead. See https://github.com/bevyengine/bevy/issues/18453 for motivation." +)] pub struct SimpleExecutor { /// Systems sets whose conditions have been evaluated. evaluated_sets: FixedBitSet, @@ -165,7 +171,10 @@ impl SimpleExecutor { } } } - +#[deprecated( + since = "0.17.0", + note = "Use SingleThreadedExecutor instead. See https://github.com/bevyengine/bevy/issues/18453 for motivation." +)] fn evaluate_and_fold_conditions(conditions: &mut [BoxedCondition], world: &mut World) -> bool { let error_handler = default_error_handler(); diff --git a/crates/bevy_ecs/src/schedule/mod.rs b/crates/bevy_ecs/src/schedule/mod.rs index aeaf8e3929..d021eb5ca3 100644 --- a/crates/bevy_ecs/src/schedule/mod.rs +++ b/crates/bevy_ecs/src/schedule/mod.rs @@ -1237,6 +1237,7 @@ mod tests { /// verify the [`SimpleExecutor`] supports stepping #[test] + #[expect(deprecated, reason = "We still need to test this.")] fn simple_executor() { assert_executor_supports_stepping!(ExecutorKind::Simple); } diff --git a/crates/bevy_ecs/src/schedule/schedule.rs b/crates/bevy_ecs/src/schedule/schedule.rs index 584e621bf8..a754f1e1d4 100644 --- a/crates/bevy_ecs/src/schedule/schedule.rs +++ b/crates/bevy_ecs/src/schedule/schedule.rs @@ -218,6 +218,7 @@ impl Schedules { fn make_executor(kind: ExecutorKind) -> Box { match kind { + #[expect(deprecated, reason = "We still need to support this.")] ExecutorKind::Simple => Box::new(SimpleExecutor::new()), ExecutorKind::SingleThreaded => Box::new(SingleThreadedExecutor::new()), #[cfg(feature = "std")] diff --git a/release-content/migration-guides/simple_executor_going_away.md b/release-content/migration-guides/simple_executor_going_away.md new file mode 100644 index 0000000000..fa029c2613 --- /dev/null +++ b/release-content/migration-guides/simple_executor_going_away.md @@ -0,0 +1,25 @@ +--- +title: Deprecated Simple Executor +pull_requests: [18753] +--- + +Bevy has deprecated `SimpleExecutor`, one of the `SystemExecutor`s in Bevy alongside `SingleThreadedExecutor` and `MultiThreadedExecutor` (which aren't going anywhere any time soon). + +The `SimpleExecutor` leaves performance on the table compared to the other executors in favor of simplicity. +Specifically, `SimpleExecutor` applies any commands a system produces right after it finishes, so every system starts with a clean `World` with no pending commands. +As a result, the default `SimpleExecutor` runs all systems in the order they are added to the schedule, though more ordering constraints can be applied, like `before`, `after`, `chain`, etc. +In other executors, these ordering onstraints also inform the executor exactly where to apply commands. +For example, if system `A` produces commands and runs `before` system `B`, `A`'s commands will be applied before `B` starts. +However, the `before` ordering is implicit in `SimpleExecutor` if `A` is added to the schedule before `B`. + +The dueling behavior between ordering systems based on when they were added to a schedule as opposed to using ordering constraints is difficult to maintain and can be confusing, especially for new users. +But, if you have a strong preference for the existing behavior of `SimpleExecutor`, please make an issue and we can discuss your needs. + +If you were using `SimpleExecutor`, consider upgrading to `SingleThreadedExecutor` instead, or try `MultiThreadedExecutor` if it fits the schedule. +The `MultiThreadedExecutor` is great at large schedules and async heavy work, and the `SingleThreadedExecutor` is good at smaller schedules or schedules that have fewer parallelizable systems. +So what was `SimpleExecutor` good at? Not much. That's why we plan to remove it. Removing it will reduce some maintenance and consistency burdens, allowing us to focus on more exciting features! + +When migrating, you might uncover bugs where one system depends on another's commands but is not ordered to reflect that. +These bugs can be fixed by making those implicit orderings explicit via constraints like `before`, `after`, `chain`, etc. +If finding all of those implicit but necessary orderings is unrealistic, `chain` can also be used to mimic the behavior of the `SimpleExecutor`. +Again, if you run into trouble migrating, feel free to open an issue!