new Diagnostics system
This commit is contained in:
parent
0073f4a58b
commit
93bf728475
@ -5,7 +5,8 @@ fn main() {
|
|||||||
App::build()
|
App::build()
|
||||||
.add_defaults()
|
.add_defaults()
|
||||||
.add_system(build_move_system())
|
.add_system(build_move_system())
|
||||||
.add_system(bevy::diagnostics::build_fps_printer_system())
|
.add_default_diagnostics()
|
||||||
|
.print_diagnostics(std::time::Duration::from_secs_f64(1.0))
|
||||||
.setup_world(setup)
|
.setup_world(setup)
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,7 +24,6 @@ fn main() {
|
|||||||
.add_system(build_wander_system())
|
.add_system(build_wander_system())
|
||||||
.add_system(build_navigate_system())
|
.add_system(build_navigate_system())
|
||||||
.add_system(build_move_system())
|
.add_system(build_move_system())
|
||||||
.add_system(bevy::diagnostics::build_fps_printer_system())
|
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,8 @@ fn main() {
|
|||||||
App::build()
|
App::build()
|
||||||
.add_defaults()
|
.add_defaults()
|
||||||
.add_system(build_move_system())
|
.add_system(build_move_system())
|
||||||
.add_system(bevy::diagnostics::build_fps_printer_system())
|
.add_default_diagnostics()
|
||||||
|
.print_diagnostics(std::time::Duration::from_secs_f64(1.0))
|
||||||
.setup_world(setup)
|
.setup_world(setup)
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,8 @@ fn main() {
|
|||||||
.add_defaults()
|
.add_defaults()
|
||||||
.setup_world(setup)
|
.setup_world(setup)
|
||||||
.add_system(build_move_system())
|
.add_system(build_move_system())
|
||||||
.add_system(bevy::diagnostics::build_fps_printer_system())
|
.add_default_diagnostics()
|
||||||
|
.print_diagnostics(std::time::Duration::from_secs_f64(1.0))
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,7 @@ use crate::{
|
|||||||
draw_target::draw_targets::*, mesh::Mesh, pass::passes::*, pipeline::pipelines::*,
|
draw_target::draw_targets::*, mesh::Mesh, pass::passes::*, pipeline::pipelines::*,
|
||||||
render_resource::resource_providers::*, renderer::Renderer, texture::Texture, *,
|
render_resource::resource_providers::*, renderer::Renderer, texture::Texture, *,
|
||||||
},
|
},
|
||||||
ui,
|
ui, diagnostic::{Diagnostics, diagnostics},
|
||||||
};
|
};
|
||||||
|
|
||||||
use bevy_transform::{prelude::LocalToWorld, transform_system_bundle};
|
use bevy_transform::{prelude::LocalToWorld, transform_system_bundle};
|
||||||
@ -20,7 +20,7 @@ use render_resource::{
|
|||||||
EntityRenderResourceAssignments, RenderResourceAssignments,
|
EntityRenderResourceAssignments, RenderResourceAssignments,
|
||||||
};
|
};
|
||||||
use shader::Shader;
|
use shader::Shader;
|
||||||
use std::collections::HashMap;
|
use std::{time::Duration, collections::HashMap};
|
||||||
|
|
||||||
pub struct AppBuilder {
|
pub struct AppBuilder {
|
||||||
pub world: Option<World>,
|
pub world: Option<World>,
|
||||||
@ -160,6 +160,7 @@ impl AppBuilder {
|
|||||||
pub fn add_default_resources(&mut self) -> &mut Self {
|
pub fn add_default_resources(&mut self) -> &mut Self {
|
||||||
let resources = self.resources.as_mut().unwrap();
|
let resources = self.resources.as_mut().unwrap();
|
||||||
resources.insert(Time::new());
|
resources.insert(Time::new());
|
||||||
|
resources.insert(Diagnostics::default());
|
||||||
resources.insert(AssetStorage::<Mesh>::new());
|
resources.insert(AssetStorage::<Mesh>::new());
|
||||||
resources.insert(AssetStorage::<Texture>::new());
|
resources.insert(AssetStorage::<Texture>::new());
|
||||||
resources.insert(AssetStorage::<Shader>::new());
|
resources.insert(AssetStorage::<Shader>::new());
|
||||||
@ -173,6 +174,18 @@ impl AppBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_default_diagnostics(&mut self) -> &mut Self {
|
||||||
|
let frame_time_diagnostic_system = {
|
||||||
|
let resources = self.resources.as_mut().unwrap();
|
||||||
|
diagnostics::frame_time_diagnostic_system(resources, 10)
|
||||||
|
};
|
||||||
|
self.add_system(frame_time_diagnostic_system)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_diagnostics(&mut self, wait: Duration) -> &mut Self {
|
||||||
|
self.add_system(diagnostics::print_diagnostics_system(wait))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn batch_types2<T1, T2>(&mut self) -> &mut Self
|
pub fn batch_types2<T1, T2>(&mut self) -> &mut Self
|
||||||
where
|
where
|
||||||
T1: 'static,
|
T1: 'static,
|
||||||
|
|||||||
@ -3,6 +3,7 @@ use std::time::{Duration, Instant};
|
|||||||
pub struct Time {
|
pub struct Time {
|
||||||
pub delta: Duration,
|
pub delta: Duration,
|
||||||
pub instant: Instant,
|
pub instant: Instant,
|
||||||
|
pub delta_seconds_f64: f64,
|
||||||
pub delta_seconds: f32,
|
pub delta_seconds: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -11,6 +12,7 @@ impl Time {
|
|||||||
Time {
|
Time {
|
||||||
delta: Duration::from_secs(0),
|
delta: Duration::from_secs(0),
|
||||||
instant: Instant::now(),
|
instant: Instant::now(),
|
||||||
|
delta_seconds_f64: 0.0,
|
||||||
delta_seconds: 0.0,
|
delta_seconds: 0.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -21,7 +23,8 @@ impl Time {
|
|||||||
|
|
||||||
pub fn stop(&mut self) {
|
pub fn stop(&mut self) {
|
||||||
self.delta = Instant::now() - self.instant;
|
self.delta = Instant::now() - self.instant;
|
||||||
self.delta_seconds =
|
self.delta_seconds_f64 =
|
||||||
self.delta.as_secs() as f32 + (self.delta.subsec_nanos() as f32 / 1.0e9);
|
self.delta.as_secs() as f64 + (self.delta.subsec_nanos() as f64 / 1.0e9);
|
||||||
|
self.delta_seconds = self.delta_seconds_f64 as f32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
94
src/diagnostic/diagnostics.rs
Normal file
94
src/diagnostic/diagnostics.rs
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
use super::{Diagnostic, DiagnosticId, Diagnostics};
|
||||||
|
use crate::{
|
||||||
|
core::Time,
|
||||||
|
prelude::{Resources, SystemBuilder},
|
||||||
|
};
|
||||||
|
use legion::prelude::Schedulable;
|
||||||
|
use std::time::Duration;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
pub const FPS: DiagnosticId = DiagnosticId(Uuid::from_bytes([
|
||||||
|
157, 191, 0, 72, 223, 223, 70, 128, 137, 117, 54, 177, 132, 13, 170, 124,
|
||||||
|
]));
|
||||||
|
|
||||||
|
pub const FRAME_TIME: DiagnosticId = DiagnosticId(Uuid::from_bytes([
|
||||||
|
216, 184, 55, 12, 28, 116, 69, 201, 187, 137, 176, 77, 83, 89, 251, 241,
|
||||||
|
]));
|
||||||
|
|
||||||
|
pub fn frame_time_diagnostic_system(
|
||||||
|
resources: &Resources,
|
||||||
|
max_history_length: usize,
|
||||||
|
) -> Box<dyn Schedulable> {
|
||||||
|
let mut diagnostics = resources.get_mut::<Diagnostics>().unwrap();
|
||||||
|
diagnostics.add(Diagnostic::new(
|
||||||
|
FRAME_TIME,
|
||||||
|
"frame_time",
|
||||||
|
max_history_length,
|
||||||
|
));
|
||||||
|
diagnostics.add(Diagnostic::new(FPS, "fps", max_history_length));
|
||||||
|
SystemBuilder::new("FrameTimeDiagnostic")
|
||||||
|
.read_resource::<Time>()
|
||||||
|
.write_resource::<Diagnostics>()
|
||||||
|
.build(move |_, _world, (time, ref mut diagnostics), _queries| {
|
||||||
|
if time.delta_seconds_f64 == 0.0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
diagnostics.add_measurement(FRAME_TIME, time.delta_seconds_f64);
|
||||||
|
if let Some(fps) = diagnostics
|
||||||
|
.get(FRAME_TIME)
|
||||||
|
.and_then(|frame_time_diagnostic| {
|
||||||
|
frame_time_diagnostic
|
||||||
|
.average()
|
||||||
|
.and_then(|frame_time_average| {
|
||||||
|
if frame_time_average > 0.0 {
|
||||||
|
Some(1.0 / frame_time_average)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
{
|
||||||
|
diagnostics.add_measurement(FPS, fps);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_diagnostics_system(wait: Duration) -> Box<dyn Schedulable> {
|
||||||
|
let mut elasped = 0.0;
|
||||||
|
let wait_seconds = wait.as_secs_f64();
|
||||||
|
SystemBuilder::new("PrintDiagnostics")
|
||||||
|
.read_resource::<Time>()
|
||||||
|
.read_resource::<Diagnostics>()
|
||||||
|
.build(move |_, _world, (time, diagnostics), _queries| {
|
||||||
|
elasped += time.delta_seconds_f64;
|
||||||
|
if elasped >= wait_seconds {
|
||||||
|
elasped = 0.0;
|
||||||
|
for diagnostic in diagnostics.iter() {
|
||||||
|
if let Some(value) = diagnostic.value() {
|
||||||
|
println!("{}: {}", diagnostic.name, value);
|
||||||
|
if let Some(average) = diagnostic.average() {
|
||||||
|
println!(" average: {}", average);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_diagnostics_debug_system(wait: Duration) -> Box<dyn Schedulable> {
|
||||||
|
let mut elasped = 0.0;
|
||||||
|
let wait_seconds = wait.as_secs_f64();
|
||||||
|
SystemBuilder::new("PrintDiagnostics")
|
||||||
|
.read_resource::<Time>()
|
||||||
|
.read_resource::<Diagnostics>()
|
||||||
|
.build(move |_, _world, (time, diagnostics), _queries| {
|
||||||
|
elasped += time.delta_seconds_f64;
|
||||||
|
if elasped >= wait_seconds {
|
||||||
|
elasped = 0.0;
|
||||||
|
for diagnostic in diagnostics.iter() {
|
||||||
|
println!("{:#?}\n", diagnostic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
124
src/diagnostic/mod.rs
Normal file
124
src/diagnostic/mod.rs
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
pub mod diagnostics;
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
collections::{HashMap, VecDeque},
|
||||||
|
time::{Duration, SystemTime},
|
||||||
|
};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
|
||||||
|
pub struct DiagnosticId(Uuid);
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct DiagnosticMeasurement {
|
||||||
|
pub time: SystemTime,
|
||||||
|
pub value: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Diagnostic {
|
||||||
|
pub id: DiagnosticId,
|
||||||
|
pub name: String,
|
||||||
|
history: VecDeque<DiagnosticMeasurement>,
|
||||||
|
sum: f64,
|
||||||
|
max_history_length: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Diagnostic {
|
||||||
|
pub fn add_measurement(&mut self, value: f64) {
|
||||||
|
let time = SystemTime::now();
|
||||||
|
if self.history.len() == self.max_history_length {
|
||||||
|
if let Some(removed_diagnostic) = self.history.pop_back() {
|
||||||
|
self.sum -= removed_diagnostic.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.sum += value;
|
||||||
|
self.history.push_front(DiagnosticMeasurement {
|
||||||
|
time,
|
||||||
|
value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(id: DiagnosticId, name: &str, max_history_length: usize) -> Diagnostic {
|
||||||
|
Diagnostic {
|
||||||
|
id,
|
||||||
|
name: name.to_string(),
|
||||||
|
history: VecDeque::with_capacity(max_history_length),
|
||||||
|
max_history_length,
|
||||||
|
sum: 0.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn value(&self) -> Option<f64> {
|
||||||
|
self.history.back().map(|measurement| measurement.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sum(&self) -> f64 {
|
||||||
|
self.sum
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn average(&self) -> Option<f64> {
|
||||||
|
if self.history.len() > 0 {
|
||||||
|
Some(self.sum / self.history.len() as f64)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn history_len(&self) -> usize {
|
||||||
|
self.history.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn duration(&self) -> Option<Duration> {
|
||||||
|
if self.history.len() < 2 {
|
||||||
|
return None
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(oldest) = self.history.back() {
|
||||||
|
if let Some(newest) = self.history.front() {
|
||||||
|
return newest.time.duration_since(oldest.time).ok()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_max_history_length(&self) -> usize {
|
||||||
|
self.max_history_length
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Diagnostics {
|
||||||
|
diagnostics: HashMap<DiagnosticId, Diagnostic>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Diagnostics {
|
||||||
|
pub fn add(&mut self, diagnostic: Diagnostic) {
|
||||||
|
self.diagnostics.insert(diagnostic.id, diagnostic);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(&self, id: DiagnosticId) -> Option<&Diagnostic> {
|
||||||
|
self.diagnostics.get(&id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_mut(&mut self, id: DiagnosticId) -> Option<&mut Diagnostic> {
|
||||||
|
self.diagnostics.get_mut(&id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_measurement(&self, id: DiagnosticId) -> Option<&DiagnosticMeasurement> {
|
||||||
|
self.diagnostics.get(&id).and_then(|diagnostic| diagnostic.history.front())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_measurement(&mut self, id: DiagnosticId, value: f64) {
|
||||||
|
if let Some(diagnostic) = self.diagnostics.get_mut(&id) {
|
||||||
|
diagnostic.add_measurement(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter(&self) -> impl Iterator<Item=&Diagnostic> {
|
||||||
|
self.diagnostics.values()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,32 +0,0 @@
|
|||||||
use crate::{core::Time, prelude::SystemBuilder};
|
|
||||||
use legion::prelude::Schedulable;
|
|
||||||
use std::collections::VecDeque;
|
|
||||||
|
|
||||||
pub fn build_fps_printer_system() -> Box<dyn Schedulable> {
|
|
||||||
let mut elapsed = 0.0;
|
|
||||||
let mut frame_time_total = 0.0;
|
|
||||||
let mut frame_time_count = 0;
|
|
||||||
let frame_time_max = 10;
|
|
||||||
let mut frame_time_values = VecDeque::new();
|
|
||||||
SystemBuilder::new("FpsPrinter")
|
|
||||||
.read_resource::<Time>()
|
|
||||||
.build(move |_, _world, time, _queries| {
|
|
||||||
elapsed += time.delta_seconds;
|
|
||||||
frame_time_values.push_front(time.delta_seconds);
|
|
||||||
frame_time_total += time.delta_seconds;
|
|
||||||
frame_time_count += 1;
|
|
||||||
if frame_time_count > frame_time_max {
|
|
||||||
frame_time_count = frame_time_max;
|
|
||||||
frame_time_total -= frame_time_values.pop_back().unwrap();
|
|
||||||
}
|
|
||||||
if elapsed > 1.0 {
|
|
||||||
if frame_time_count > 0 && frame_time_total > 0.0 {
|
|
||||||
println!(
|
|
||||||
"fps: {}",
|
|
||||||
1.0 / (frame_time_total / frame_time_count as f32)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
elapsed = 0.0;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@ -2,7 +2,7 @@
|
|||||||
pub mod app;
|
pub mod app;
|
||||||
pub mod asset;
|
pub mod asset;
|
||||||
pub mod core;
|
pub mod core;
|
||||||
pub mod diagnostics;
|
pub mod diagnostic;
|
||||||
pub mod ecs;
|
pub mod ecs;
|
||||||
pub mod plugin;
|
pub mod plugin;
|
||||||
pub mod prelude;
|
pub mod prelude;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user