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 <alice.i.cecile@gmail.com>
Co-authored-by: Cyrill Schenkel <cyrill.schenkel@gmail.com>
This commit is contained in:
Eagster 2025-05-05 20:21:57 -04:00 committed by GitHub
parent cdcb773e9b
commit af8d12c3e1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 45 additions and 1 deletions

View File

@ -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()));

View File

@ -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);

View File

@ -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();

View File

@ -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);
}

View File

@ -218,6 +218,7 @@ impl Schedules {
fn make_executor(kind: ExecutorKind) -> Box<dyn SystemExecutor> {
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")]

View File

@ -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!