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

Better warnings about invalid parameters #15500

Merged
merged 14 commits into from
Oct 3, 2024

Conversation

MiniaczQ
Copy link
Contributor

@MiniaczQ MiniaczQ commented Sep 28, 2024

Objective

System param validation warnings should be configurable and default to "warn once" (per system).

Fixes: #15391

Solution

SystemMeta is given a new ParamWarnPolicy field.
The policy decides whether warnings will be emitted by each system param when it fails validation.
The policy is updated by the system after param validation fails.

Example warning:

2024-09-30T18:10:04.740749Z  WARN bevy_ecs::system::function_system: System fallible_params::do_nothing_fail_validation will not run because it requested inaccessible system parameter Single<(), (With<Player>, With<Enemy>)>

Currently, only the first invalid parameter is displayed.

Warnings can be disabled on function systems using .param_never_warn().
(there is also .with_param_warn_policy(policy))

Testing

Ran fallible_params example.

@MiniaczQ MiniaczQ added C-Feature A new feature, making something new possible A-ECS Entities, components, systems, and events S-Blocked This cannot move forward until something else changes X-Uncontroversial This work is generally agreed upon labels Sep 28, 2024
@MiniaczQ MiniaczQ added this to the 0.15 milestone Sep 28, 2024
@alice-i-cecile alice-i-cecile added S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged and removed S-Blocked This cannot move forward until something else changes labels Sep 28, 2024
@MiniaczQ MiniaczQ marked this pull request as ready for review September 28, 2024 20:12
@MiniaczQ MiniaczQ added S-Needs-Review Needs reviewer attention (from anyone!) to move forward and removed S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged labels Sep 28, 2024
@BenjaminBrienen BenjaminBrienen added the D-Straightforward Simple bug fixes and API improvements, docs, test and examples label Sep 28, 2024
@MiniaczQ
Copy link
Contributor Author

I've noticed some problems with this approach, I'll be reworking it

@MiniaczQ MiniaczQ added S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged and removed S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Sep 29, 2024
@MiniaczQ MiniaczQ added D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes X-Contentious There are nontrivial implications that should be thought through and removed D-Straightforward Simple bug fixes and API improvements, docs, test and examples X-Uncontroversial This work is generally agreed upon labels Sep 30, 2024
github-merge-queue bot pushed a commit that referenced this pull request Sep 30, 2024
…15526)

# Objective

Fixes #15394

## Solution

Observers now validate params.

System registry has a new error variant for when system running fails
due to invalid parameters.

Run once now returns a `Result<Out, RunOnceError>` instead of `Out`.
This is more inline with system registry, which also returns a result.

I'll address warning messages in #15500.

## Testing

Added one test for each case.

---

## Migration Guide

- `RunSystemOnce::run_system_once` and
`RunSystemOnce::run_system_once_with` now return a `Result<Out>` instead
of just `Out`

---------

Co-authored-by: Alice Cecile <[email protected]>
Co-authored-by: Zachary Harrold <[email protected]>
@MiniaczQ MiniaczQ marked this pull request as ready for review September 30, 2024 02:17
Copy link
Contributor

@SpecificProtagonist SpecificProtagonist left a comment

Choose a reason for hiding this comment

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

This approach looks good.

Added a new bevy_ecs default feature flag bevy_warn_invalid_param which enables the warnings.
Disabling it can slightly improve performance due to reduced checks when running each system.

Have you benchmarked this? Two not taken (predictable) ifs per system invocation probably aren't measurable and not worth adding a system flag.

I'm not convinced we need WarnPolicy::Always, but I don't have much of an opinion on it.

I do however think it makes sense to rename WarnPolicy to ParamWarnPolicy, as it is about param validation and doesn't affect bevy::log::warn.

@MiniaczQ
Copy link
Contributor Author

Have you benchmarked this? Two not taken (predictable) ifs per system invocation probably aren't measurable and not worth adding a system flag.

Not benchmarked, I'll see if next reviewer agrees or if we'll need benchmarks.

@SpecificProtagonist
Copy link
Contributor

SpecificProtagonist commented Sep 30, 2024

Trying to construct a worst-case benchmark, where the systems do no work and there are no parameters to validate or extract:

let mut world = World::new();
let mut schedule = Schedule::default();
for _ in 0..1000 {
    schedule.add_systems(|| ());
}
for _ in 0..1000000 {
    schedule.run(&mut world);
}
With bevy_param_warn:
  Time (mean ± σ):     13.639 s ±  0.147 s    [User: 13.590 s, System: 0.025 s]
  Range (min … max):   13.484 s … 13.982 s    10 runs

Without:
  Time (mean ± σ):     13.817 s ±  0.196 s    [User: 13.772 s, System: 0.025 s]
  Range (min … max):   13.539 s … 14.250 s    10 runs

So there's about a standard deviation difference. But if these numbers were precise, the feature flag would allow removing 0.178ns per system. I don't think that's worth it.

@MiniaczQ
Copy link
Contributor Author

Thank you for your work, I'll remove the flag when im home :)

Copy link
Contributor

@chescock chescock left a comment

Choose a reason for hiding this comment

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

So the warning is now emitted from the param itself, which lets you include the param type in the message. And the warning state is stored on the system, which saves space and is easier to configure. As a consequence, if a system has multiple failing parameters, it only warns on the first one, right? That all seems reasonable, although the final result is a little surprising.

crates/bevy_ecs/src/system/function_system.rs Outdated Show resolved Hide resolved
crates/bevy_ecs/src/system/function_system.rs Outdated Show resolved Hide resolved
crates/bevy_ecs/src/system/function_system.rs Outdated Show resolved Hide resolved
@MiniaczQ
Copy link
Contributor Author

MiniaczQ commented Sep 30, 2024

if a system has multiple failing parameters, it only warns on the first one, right?

The policy update of a (function) system happens after param validation fails.
But param validation of tuples, etc. currently short circuits, so yes
you will only see the first missing type.

While we can remove the short circuit, this won't patch a hole where missing parameters can change over time and we'll still only get warning about the first one (time-wise).

I guess we could store the warning per system param??
But then routing all the configuration will be hellish

Copy link
Contributor

@bushrat011899 bushrat011899 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 to me, love the idea of giving more meaningful feedback to the user without spamming them needlessly. I have a note about a possible future PR, but definitely doesn't need to be in this PR.

/// No warning should ever be emitted.
Never,
/// The warning will be emitted once and status will update to [`Self::Never`].
Once,
Copy link
Contributor

Choose a reason for hiding this comment

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

Future PR: Seems reasonable to add an Always policy as well:

/// State machine for emitting warnings when [system params are invalid](System::validate_param).
#[derive(Clone, Copy)]
pub enum ParamWarnPolicy {
    /// No warning should ever be emitted.
    Never,
    /// The warning will be emitted once and status will update to [`Self::Never`].
    Once,
    /// The warning will be emitted each time the system is run.
    Always,
}

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 had it but removed it as per previous feedback.
I think Always will be a bit too annoying, but we could certainly use more complex policies:

  • system just stopped running (prev frame valid, this frame invalid)
  • invalid params changed

If we get some higher level logging with editor, we can do stuff like:

  • system X stopped running at frame N because of invalid param P and is still not running till frame M

@bushrat011899 bushrat011899 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
Copy link
Contributor

@SpecificProtagonist SpecificProtagonist left a comment

Choose a reason for hiding this comment

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

Hm, I don't think we have a good way to test whether the right things get logged?

btw the PR description still mentions bevy_param_warn

Anyway, the implementation is looking good to me!

crates/bevy_ecs/src/system/function_system.rs Outdated Show resolved Hide resolved
crates/bevy_ecs/src/system/function_system.rs Outdated Show resolved Hide resolved
@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 acea4e7 Oct 3, 2024
26 checks passed
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-Feature A new feature, making something new possible D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes 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.

Logging for system parameter validation should be configurable
6 participants