Skip to content
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

Add try_despawn methods to World/Commands #15480

Merged
merged 20 commits into from
Oct 3, 2024

Conversation

rudderbucky
Copy link
Contributor

@rudderbucky rudderbucky commented Sep 27, 2024

Objective

Fixes #14511.

despawn allows you to remove entities from the world. However, if the entity does not exist, it emits a warning. This may not be intended behavior for many users who have use cases where they need to call despawn regardless of if the entity actually exists (see the issue), or don't care in general if the entity already doesn't exist.

(Also trying to gauge interest on if this feature makes sense, I'd personally love to have it, but I could see arguments that this might be a footgun. Just trying to help here 😄 If there's no contention I could also implement this for despawn_recursive and despawn_descendants in the same PR)

Solution

Add try_despawn, try_despawn_recursive and try_despawn_descendants.

Modify World::despawn_with_caller to also take in a warn boolean argument, which is then considered when logging the warning. Set log_warning to true in the case of despawn, and false in the case of try_despawn.

Testing

Ran cargo run -p ci on macOS, it seemed fine.

@alice-i-cecile alice-i-cecile added D-Trivial Nice and easy! A great choice to get started with Bevy A-ECS Entities, components, systems, and events C-Usability A targeted quality-of-life change that makes Bevy easier to use X-Contentious There are nontrivial implications that should be thought through S-Needs-Review Needs reviewer attention (from anyone!) to move forward D-Straightforward Simple bug fixes and API improvements, docs, test and examples and removed D-Trivial Nice and easy! A great choice to get started with Bevy labels Sep 27, 2024
@rudderbucky
Copy link
Contributor Author

@alice-i-cecile added in the try_despawn_recursive commands. I did it super naively, but could I get some assignees to discuss this with? Thanks!

Comment on lines 23 to 36
/// Despawns the given entity and all its children recursively without warnings
#[derive(Debug)]
pub struct TryDespawnRecursive {
/// Target entity
pub entity: Entity,
}

/// Despawns the given entity's children recursively without warnings
#[derive(Debug)]
pub struct TryDespawnChildrenRecursive {
/// Target entity
pub entity: Entity,
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can add warn flag to the existing commands

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm somewhat against this due to the additional skew it creates for the PR, and that this introduces a breaking change. A similar pattern of non-try/try pairing exists for Query::single and Query::get_single, which I would prefer here as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just pushed some commits with this change though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I just noticed the new changes
How I see it is, we can keep user command/world API like despawn, try_despawn
but all the internals can just use the flag, so that's command structs and functions that do the despawning

that way we have no breaking changes and we can keep the internals concise

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, if I've been a bit clearer it'd save you some work

Copy link
Contributor Author

@rudderbucky rudderbucky Oct 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding is that the DespawnRecursive and DespawnChildrenRecursive command structs are exposed to users, so this would still introduce a breaking change, no?

Copy link
Contributor

@MiniaczQ MiniaczQ Oct 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot of the engine is public to the user if they desire to access it,
but I'd consider the despawn, etc. methods to be the main way of using this API
So changing the command structs wouldn't be considered breaking change for typical user

I hope that makes sense?

@rudderbucky
Copy link
Contributor Author

@MiniaczQ PTAL at the changes

Copy link
Contributor

@MiniaczQ MiniaczQ left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

@rudderbucky
Copy link
Contributor Author

@mockersf @janhohenheim PTAL when you get the chance, thanks!

Copy link
Contributor

@kristoff3r kristoff3r left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense to me

crates/bevy_hierarchy/src/hierarchy.rs Outdated Show resolved Hide resolved
crates/bevy_hierarchy/src/hierarchy.rs Outdated Show resolved Hide resolved
@alice-i-cecile alice-i-cecile added S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it and removed S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Oct 2, 2024
@alice-i-cecile
Copy link
Member

Related to #2004 and #14231. @rudderbucky, have you benchmarked this to make sure we're not getting any performance regressions when despawning large numbers of entities due to the branching?

@rudderbucky
Copy link
Contributor Author

Here is the control:

Finished `bench` profile [optimized] target(s) in 0.30s
     Running benches/bevy_math/bezier.rs (target/release/deps/bezier-a5bc02a487b0b0d7)
Gnuplot not found, using plotters backend
     Running benches/bevy_ecs/change_detection.rs (target/release/deps/change_detection-0329f8a28782566d)
Gnuplot not found, using plotters backend
     Running benches/bevy_ecs/benches.rs (target/release/deps/ecs-4ef040d4dff831f2)
Gnuplot not found, using plotters backend
despawn_world/1_entities
                        time:   [3.1699 ns 3.1711 ns 3.1722 ns]
                        change: [-4.8596% -3.9295% -3.0456%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 811 outliers among 5000 measurements (16.22%)
  164 (3.28%) low severe
  144 (2.88%) low mild
  208 (4.16%) high mild
  295 (5.90%) high severe
despawn_world/10_entities
                        time:   [29.088 ns 29.116 ns 29.146 ns]
                        change: [-3.6793% -2.4919% -1.5721%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 795 outliers among 5000 measurements (15.90%)
  182 (3.64%) low mild
  285 (5.70%) high mild
  328 (6.56%) high severe
despawn_world/100_entities
                        time:   [295.67 ns 297.45 ns 299.59 ns]
                        change: [-0.2809% +0.2536% +0.8482%] (p = 0.41 > 0.05)
                        No change in performance detected.
Found 280 outliers among 5000 measurements (5.60%)
  163 (3.26%) high mild
  117 (2.34%) high severe
despawn_world/1000_entities
                        time:   [2.8708 µs 2.8739 µs 2.8774 µs]
                        change: [-0.4241% -0.2958% -0.1479%] (p = 0.00 < 0.05)
                        Change within noise threshold.
Found 957 outliers among 5000 measurements (19.14%)
  344 (6.88%) low mild
  260 (5.20%) high mild
  353 (7.06%) high severe
despawn_world/10000_entities
                        time:   [28.544 µs 28.569 µs 28.602 µs]
                        change: [-0.5647% -0.4562% -0.3028%] (p = 0.00 < 0.05)
                        Change within noise threshold.
Found 911 outliers among 5000 measurements (18.22%)
  267 (5.34%) low severe
  51 (1.02%) low mild
  214 (4.28%) high mild
  379 (7.58%) high severe

despawn_world_recursive/1_entities
                        time:   [10.177 ns 10.193 ns 10.213 ns]
                        change: [-0.1700% +0.1427% +0.4951%] (p = 0.42 > 0.05)
                        No change in performance detected.
Found 931 outliers among 5000 measurements (18.62%)
  238 (4.76%) low severe
  43 (0.86%) low mild
  281 (5.62%) high mild
  369 (7.38%) high severe
despawn_world_recursive/10_entities
                        time:   [108.87 ns 108.95 ns 109.04 ns]
                        change: [+0.8850% +1.0442% +1.2613%] (p = 0.00 < 0.05)
                        Change within noise threshold.
Found 329 outliers among 5000 measurements (6.58%)
  177 (3.54%) high mild
  152 (3.04%) high severe
despawn_world_recursive/100_entities
                        time:   [1.0271 µs 1.0282 µs 1.0294 µs]
                        change: [-0.9936% -0.7069% -0.4732%] (p = 0.00 < 0.05)
                        Change within noise threshold.
Found 357 outliers among 5000 measurements (7.14%)
  239 (4.78%) high mild
  118 (2.36%) high severe
despawn_world_recursive/1000_entities
                        time:   [10.258 µs 10.292 µs 10.332 µs]
                        change: [-0.1995% +0.1480% +0.5466%] (p = 0.47 > 0.05)
                        No change in performance detected.
Found 680 outliers among 5000 measurements (13.60%)
  302 (6.04%) high mild
  378 (7.56%) high severe
despawn_world_recursive/10000_entities
                        time:   [101.54 µs 101.59 µs 101.64 µs]
                        change: [-7.5469% -6.1279% -4.8684%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 912 outliers among 5000 measurements (18.24%)
  239 (4.78%) low severe
  39 (0.78%) low mild
  188 (3.76%) high mild
  446 (8.92%) high severe

And this branch:

Finished `bench` profile [optimized] target(s) in 2m 25s
     Running benches/bevy_math/bezier.rs (target/release/deps/bezier-a5bc02a487b0b0d7)
Gnuplot not found, using plotters backend
     Running benches/bevy_ecs/change_detection.rs (target/release/deps/change_detection-0329f8a28782566d)
Gnuplot not found, using plotters backend
     Running benches/bevy_ecs/benches.rs (target/release/deps/ecs-4ef040d4dff831f2)
Gnuplot not found, using plotters backend
despawn_world/1_entities
                        time:   [3.2177 ns 3.2496 ns 3.2896 ns]
                        change: [+1.0881% +1.5525% +2.3328%] (p = 0.00 < 0.05)
                        Performance has regressed.
Found 286 outliers among 5000 measurements (5.72%)
  186 (3.72%) high mild
  100 (2.00%) high severe
despawn_world/10_entities
                        time:   [30.525 ns 31.224 ns 32.115 ns]
                        change: [+3.4925% +5.2023% +7.3514%] (p = 0.00 < 0.05)
                        Performance has regressed.
Found 398 outliers among 5000 measurements (7.96%)
  196 (3.92%) high mild
  202 (4.04%) high severe
despawn_world/100_entities
                        time:   [290.54 ns 293.11 ns 297.25 ns]
                        change: [-2.0964% -1.2883% -0.3538%] (p = 0.00 < 0.05)
                        Change within noise threshold.
Found 331 outliers among 5000 measurements (6.62%)
  222 (4.44%) high mild
  109 (2.18%) high severe
despawn_world/1000_entities
                        time:   [2.8573 µs 2.8596 µs 2.8619 µs]
                        change: [-0.6438% -0.4982% -0.3638%] (p = 0.00 < 0.05)
                        Change within noise threshold.
Found 337 outliers among 5000 measurements (6.74%)
  201 (4.02%) high mild
  136 (2.72%) high severe
despawn_world/10000_entities
                        time:   [28.603 µs 28.684 µs 28.795 µs]
                        change: [+0.0942% +0.4014% +0.8193%] (p = 0.01 < 0.05)
                        Change within noise threshold.
Found 417 outliers among 5000 measurements (8.34%)
  227 (4.54%) high mild
  190 (3.80%) high severe

despawn_world_recursive/1_entities
                        time:   [10.791 ns 10.811 ns 10.838 ns]
                        change: [+5.5902% +6.0467% +6.4699%] (p = 0.00 < 0.05)
                        Performance has regressed.
Found 382 outliers among 5000 measurements (7.64%)
  234 (4.68%) high mild
  148 (2.96%) high severe
despawn_world_recursive/10_entities
                        time:   [108.08 ns 108.23 ns 108.42 ns]
                        change: [-1.2305% -0.8164% -0.2306%] (p = 0.00 < 0.05)
                        Change within noise threshold.
Found 353 outliers among 5000 measurements (7.06%)
  200 (4.00%) high mild
  153 (3.06%) high severe
despawn_world_recursive/100_entities
                        time:   [1.0295 µs 1.0308 µs 1.0321 µs]
                        change: [+0.0769% +0.2496% +0.4156%] (p = 0.00 < 0.05)
                        Change within noise threshold.
Found 421 outliers among 5000 measurements (8.42%)
  225 (4.50%) high mild
  196 (3.92%) high severe
despawn_world_recursive/1000_entities
                        time:   [10.188 µs 10.213 µs 10.247 µs]
                        change: [-1.2326% -0.7698% -0.2844%] (p = 0.00 < 0.05)
                        Change within noise threshold.
Found 417 outliers among 5000 measurements (8.34%)
  245 (4.90%) high mild
  172 (3.44%) high severe
despawn_world_recursive/10000_entities
                        time:   [102.87 µs 103.39 µs 103.99 µs]
                        change: [+1.2313% +1.7739% +2.3266%] (p = 0.00 < 0.05)
                        Performance has regressed.
Found 470 outliers among 5000 measurements (9.40%)
  237 (4.74%) high mild
  233 (4.66%) high severe

The outcomes do change basically every time I run this, even with N=5000. @alice-i-cecile up to you for interpretation

@alice-i-cecile
Copy link
Member

I'm going to call this "basically within noise". As a scientist, I don't have any degree of confidence that there's a regression here, and if it is, it's a small regression on a minor (but not zero) operation. Merging.

@alice-i-cecile alice-i-cecile added this pull request to the merge queue Oct 3, 2024
Merged via the queue into bevyengine:main with commit 2da8d17 Oct 3, 2024
26 checks passed
ItsDoot pushed a commit to ItsDoot/bevy that referenced this pull request Oct 4, 2024
# Objective

Fixes bevyengine#14511.

`despawn` allows you to remove entities from the world. However, if the
entity does not exist, it emits a warning. This may not be intended
behavior for many users who have use cases where they need to call
`despawn` regardless of if the entity actually exists (see the issue),
or don't care in general if the entity already doesn't exist.

(Also trying to gauge interest on if this feature makes sense, I'd
personally love to have it, but I could see arguments that this might be
a footgun. Just trying to help here 😄 If there's no contention I could
also implement this for `despawn_recursive` and `despawn_descendants` in
the same PR)

## Solution

Add `try_despawn`, `try_despawn_recursive` and
`try_despawn_descendants`.

Modify `World::despawn_with_caller` to also take in a `warn` boolean
argument, which is then considered when logging the warning. Set
`log_warning` to `true` in the case of `despawn`, and `false` in the
case of `try_despawn`.

## Testing

Ran `cargo run -p ci` on macOS, it seemed fine.
robtfm pushed a commit to robtfm/bevy that referenced this pull request Oct 4, 2024
# Objective

Fixes bevyengine#14511.

`despawn` allows you to remove entities from the world. However, if the
entity does not exist, it emits a warning. This may not be intended
behavior for many users who have use cases where they need to call
`despawn` regardless of if the entity actually exists (see the issue),
or don't care in general if the entity already doesn't exist.

(Also trying to gauge interest on if this feature makes sense, I'd
personally love to have it, but I could see arguments that this might be
a footgun. Just trying to help here 😄 If there's no contention I could
also implement this for `despawn_recursive` and `despawn_descendants` in
the same PR)

## Solution

Add `try_despawn`, `try_despawn_recursive` and
`try_despawn_descendants`.

Modify `World::despawn_with_caller` to also take in a `warn` boolean
argument, which is then considered when logging the warning. Set
`log_warning` to `true` in the case of `despawn`, and `false` in the
case of `try_despawn`.

## Testing

Ran `cargo run -p ci` on macOS, it seemed fine.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ECS Entities, components, systems, and events C-Usability A targeted quality-of-life change that makes Bevy easier to use D-Straightforward Simple bug fixes and API improvements, docs, test and examples S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it X-Contentious There are nontrivial implications that should be thought through
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add try_despawn methods to commands
4 participants