Allow users to customize history length in FrameTimeDiagnosticsPlugin
(#17259)
# Objective I have an application where I'd like to measure average frame rate over the entire life of the application, and it would be handy if I could just configure this on the existing `FrameTimeDiagnosticsPlugin`. Probably fixes #10948? ## Solution Add `max_history_length` to `FrameTimeDiagnosticsPlugin`, and because `smoothing_factor` seems to be based on history length, add that too. ## Discussion I'm not totally sure that `DEFAULT_MAX_HISTORY_LENGTH` is a great default for `FrameTimeDiagnosticsPlugin` (or any diagnostic?). That's 1/3 of a second at typical game frame rates. Moreover, the default print interval for `LogDiagnosticsPlugin` is 1 second. So when the two are combined, you are printing the average over the last third of the duration between now and the previous print, which seems a bit wonky. (related: #11429) I'm pretty sure this default value discussed and the current value wasn't totally arbitrary though. Maybe it would be nice for `Diagnostic` to have a `with_max_history_length_and_also_calculate_a_good_default_smoothing_factor` method? And then make an explicit smoothing factor in `FrameTimeDiagnosticsPlugin` optional? Or add a `new(max_history_length: usize)` method to `FrameTimeDiagnosticsPlugin` that sets a reasonable default `smoothing_factor`? edit: This one seems like a no-brainer, doing it. ## Alternatives It's really easy to roll your own `FrameTimeDiagnosticsPlugin`, but that might not be super interoperable with, for example, third party FPS overlays. Still, might be the right call. ## Testing `cargo run --example many_sprites` (modified to use a custom `max_history_length`) ## Migration Guide `FrameTimeDiagnosticsPlugin` now contains two fields. Use `FrameTimeDiagnosticsPlugin::default()` to match Bevy's previous behavior or, for example, `FrameTimeDiagnosticsPlugin::new(60)` to configure it.
This commit is contained in:
parent
bb0a82b9a7
commit
f0047899d7
@ -42,7 +42,7 @@ impl Plugin for FpsOverlayPlugin {
|
||||
fn build(&self, app: &mut bevy_app::App) {
|
||||
// TODO: Use plugin dependencies, see https://github.com/bevyengine/bevy/issues/69
|
||||
if !app.is_plugin_added::<FrameTimeDiagnosticsPlugin>() {
|
||||
app.add_plugins(FrameTimeDiagnosticsPlugin);
|
||||
app.add_plugins(FrameTimeDiagnosticsPlugin::default());
|
||||
}
|
||||
app.insert_resource(self.config.clone())
|
||||
.add_systems(Startup, setup)
|
||||
|
@ -1,4 +1,7 @@
|
||||
use crate::{Diagnostic, DiagnosticPath, Diagnostics, FrameCount, RegisterDiagnostic};
|
||||
use crate::{
|
||||
Diagnostic, DiagnosticPath, Diagnostics, FrameCount, RegisterDiagnostic,
|
||||
DEFAULT_MAX_HISTORY_LENGTH,
|
||||
};
|
||||
use bevy_app::prelude::*;
|
||||
use bevy_ecs::prelude::*;
|
||||
use bevy_time::{Real, Time};
|
||||
@ -8,15 +11,49 @@ use bevy_time::{Real, Time};
|
||||
/// # See also
|
||||
///
|
||||
/// [`LogDiagnosticsPlugin`](crate::LogDiagnosticsPlugin) to output diagnostics to the console.
|
||||
#[derive(Default)]
|
||||
pub struct FrameTimeDiagnosticsPlugin;
|
||||
pub struct FrameTimeDiagnosticsPlugin {
|
||||
/// The total number of values to keep for averaging.
|
||||
pub max_history_length: usize,
|
||||
/// The smoothing factor for the exponential moving average. Usually `(history_length + 1.0) / 2.0)`.
|
||||
pub smoothing_factor: f64,
|
||||
}
|
||||
impl Default for FrameTimeDiagnosticsPlugin {
|
||||
fn default() -> Self {
|
||||
Self::new(DEFAULT_MAX_HISTORY_LENGTH)
|
||||
}
|
||||
}
|
||||
impl FrameTimeDiagnosticsPlugin {
|
||||
/// Creates a new `FrameTimeDiagnosticsPlugin` with the specified `max_history_length` and a
|
||||
/// reasonable `smoothing_factor`.
|
||||
pub fn new(max_history_length: usize) -> Self {
|
||||
Self {
|
||||
max_history_length,
|
||||
smoothing_factor: (max_history_length as f64 + 1.0) / 2.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Plugin for FrameTimeDiagnosticsPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.register_diagnostic(Diagnostic::new(Self::FRAME_TIME).with_suffix("ms"))
|
||||
.register_diagnostic(Diagnostic::new(Self::FPS))
|
||||
.register_diagnostic(Diagnostic::new(Self::FRAME_COUNT).with_smoothing_factor(0.0))
|
||||
.add_systems(Update, Self::diagnostic_system);
|
||||
app.register_diagnostic(
|
||||
Diagnostic::new(Self::FRAME_TIME)
|
||||
.with_suffix("ms")
|
||||
.with_max_history_length(self.max_history_length)
|
||||
.with_smoothing_factor(self.smoothing_factor),
|
||||
)
|
||||
.register_diagnostic(
|
||||
Diagnostic::new(Self::FPS)
|
||||
.with_max_history_length(self.max_history_length)
|
||||
.with_smoothing_factor(self.smoothing_factor),
|
||||
)
|
||||
// An average frame count would be nonsensical, so we set the max history length
|
||||
// to zero and disable smoothing.
|
||||
.register_diagnostic(
|
||||
Diagnostic::new(Self::FRAME_COUNT)
|
||||
.with_smoothing_factor(0.0)
|
||||
.with_max_history_length(0),
|
||||
)
|
||||
.add_systems(Update, Self::diagnostic_system);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ fn main() {
|
||||
App::new()
|
||||
.add_plugins((
|
||||
DefaultPlugins,
|
||||
FrameTimeDiagnosticsPlugin,
|
||||
FrameTimeDiagnosticsPlugin::default(),
|
||||
LogDiagnosticsPlugin::default(),
|
||||
))
|
||||
.add_systems(
|
||||
|
@ -10,7 +10,7 @@ fn main() {
|
||||
.add_plugins((
|
||||
DefaultPlugins,
|
||||
// Adds frame time diagnostics
|
||||
FrameTimeDiagnosticsPlugin,
|
||||
FrameTimeDiagnosticsPlugin::default(),
|
||||
// Adds a system that prints diagnostics to the console
|
||||
LogDiagnosticsPlugin::default(),
|
||||
// Any plugin can register diagnostics. Uncomment this to add an entity count diagnostics:
|
||||
|
@ -142,7 +142,7 @@ fn main() {
|
||||
}),
|
||||
..default()
|
||||
}),
|
||||
FrameTimeDiagnosticsPlugin,
|
||||
FrameTimeDiagnosticsPlugin::default(),
|
||||
LogDiagnosticsPlugin::default(),
|
||||
))
|
||||
.insert_resource(WinitSettings {
|
||||
|
@ -21,7 +21,7 @@ fn main() {
|
||||
// Since this is also used as a benchmark, we want it to display performance data.
|
||||
.add_plugins((
|
||||
LogDiagnosticsPlugin::default(),
|
||||
FrameTimeDiagnosticsPlugin,
|
||||
FrameTimeDiagnosticsPlugin::default(),
|
||||
DefaultPlugins.set(WindowPlugin {
|
||||
primary_window: Some(Window {
|
||||
present_mode: PresentMode::AutoNoVsync,
|
||||
|
@ -73,7 +73,7 @@ fn main() {
|
||||
}),
|
||||
..default()
|
||||
}),
|
||||
FrameTimeDiagnosticsPlugin,
|
||||
FrameTimeDiagnosticsPlugin::default(),
|
||||
LogDiagnosticsPlugin::default(),
|
||||
))
|
||||
.insert_resource(WinitSettings {
|
||||
|
@ -146,7 +146,7 @@ fn stress_test(num_entities: u32, num_components: u32, num_systems: u32) {
|
||||
app.add_plugins(MinimalPlugins)
|
||||
.add_plugins(DiagnosticsPlugin)
|
||||
.add_plugins(LogPlugin::default())
|
||||
.add_plugins(FrameTimeDiagnosticsPlugin)
|
||||
.add_plugins(FrameTimeDiagnosticsPlugin::default())
|
||||
.add_plugins(LogDiagnosticsPlugin::filtered(vec![DiagnosticPath::new(
|
||||
"fps",
|
||||
)]));
|
||||
|
@ -111,7 +111,7 @@ fn main() {
|
||||
}),
|
||||
..default()
|
||||
}),
|
||||
FrameTimeDiagnosticsPlugin,
|
||||
FrameTimeDiagnosticsPlugin::default(),
|
||||
LogDiagnosticsPlugin::default(),
|
||||
))
|
||||
.insert_resource(WinitSettings {
|
||||
|
@ -51,7 +51,7 @@ fn main() {
|
||||
}),
|
||||
..default()
|
||||
}),
|
||||
FrameTimeDiagnosticsPlugin,
|
||||
FrameTimeDiagnosticsPlugin::default(),
|
||||
LogDiagnosticsPlugin::default(),
|
||||
))
|
||||
.insert_resource(WinitSettings {
|
||||
|
@ -23,7 +23,7 @@ fn main() {
|
||||
}),
|
||||
..default()
|
||||
}),
|
||||
FrameTimeDiagnosticsPlugin,
|
||||
FrameTimeDiagnosticsPlugin::default(),
|
||||
LogDiagnosticsPlugin::default(),
|
||||
))
|
||||
.insert_resource(WinitSettings {
|
||||
|
@ -48,7 +48,7 @@ fn main() {
|
||||
}),
|
||||
..default()
|
||||
}),
|
||||
FrameTimeDiagnosticsPlugin,
|
||||
FrameTimeDiagnosticsPlugin::default(),
|
||||
LogDiagnosticsPlugin::default(),
|
||||
))
|
||||
.insert_resource(WinitSettings {
|
||||
|
@ -28,7 +28,7 @@ fn main() {
|
||||
}),
|
||||
..default()
|
||||
}),
|
||||
FrameTimeDiagnosticsPlugin,
|
||||
FrameTimeDiagnosticsPlugin::default(),
|
||||
LogDiagnosticsPlugin::default(),
|
||||
LogVisibleLights,
|
||||
))
|
||||
|
@ -32,7 +32,7 @@ fn main() {
|
||||
// Since this is also used as a benchmark, we want it to display performance data.
|
||||
.add_plugins((
|
||||
LogDiagnosticsPlugin::default(),
|
||||
FrameTimeDiagnosticsPlugin,
|
||||
FrameTimeDiagnosticsPlugin::default(),
|
||||
DefaultPlugins.set(WindowPlugin {
|
||||
primary_window: Some(Window {
|
||||
present_mode: PresentMode::AutoNoVsync,
|
||||
|
@ -66,7 +66,7 @@ fn main() {
|
||||
let mut app = App::new();
|
||||
|
||||
app.add_plugins((
|
||||
FrameTimeDiagnosticsPlugin,
|
||||
FrameTimeDiagnosticsPlugin::default(),
|
||||
LogDiagnosticsPlugin::default(),
|
||||
DefaultPlugins.set(WindowPlugin {
|
||||
primary_window: Some(Window {
|
||||
|
@ -23,7 +23,7 @@ fn main() {
|
||||
}),
|
||||
..default()
|
||||
}),
|
||||
FrameTimeDiagnosticsPlugin,
|
||||
FrameTimeDiagnosticsPlugin::default(),
|
||||
LogDiagnosticsPlugin::default(),
|
||||
))
|
||||
.insert_resource(WinitSettings {
|
||||
|
@ -193,7 +193,7 @@ fn main() {
|
||||
exit_condition: ExitCondition::DontExit,
|
||||
..default()
|
||||
}),
|
||||
FrameTimeDiagnosticsPlugin,
|
||||
FrameTimeDiagnosticsPlugin::default(),
|
||||
LogDiagnosticsPlugin::default(),
|
||||
))
|
||||
.add_systems(Startup, setup)
|
||||
|
@ -11,7 +11,7 @@ use bevy::{
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
.add_plugins((DefaultPlugins, FrameTimeDiagnosticsPlugin))
|
||||
.add_plugins((DefaultPlugins, FrameTimeDiagnosticsPlugin::default()))
|
||||
.add_systems(Startup, setup)
|
||||
.add_systems(Update, (text_update_system, text_color_system))
|
||||
.run();
|
||||
|
@ -20,7 +20,7 @@ fn main() {
|
||||
}),
|
||||
..default()
|
||||
}),
|
||||
FrameTimeDiagnosticsPlugin,
|
||||
FrameTimeDiagnosticsPlugin::default(),
|
||||
))
|
||||
.add_systems(Startup, infotext_system)
|
||||
.add_systems(Update, change_text_system)
|
||||
|
@ -37,7 +37,7 @@ fn main() {
|
||||
..default()
|
||||
}),
|
||||
LogDiagnosticsPlugin::default(),
|
||||
FrameTimeDiagnosticsPlugin,
|
||||
FrameTimeDiagnosticsPlugin::default(),
|
||||
))
|
||||
.add_systems(Startup, init_cursor_icons)
|
||||
.add_systems(
|
||||
|
Loading…
Reference in New Issue
Block a user