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

updates on diagnostics (log + new diagnostics) #1085

Merged
merged 7 commits into from
Dec 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,8 @@ name = "custom_diagnostic"
path = "examples/diagnostics/custom_diagnostic.rs"

[[example]]
name = "print_diagnostics"
path = "examples/diagnostics/print_diagnostics.rs"
name = "log_diagnostics"
path = "examples/diagnostics/log_diagnostics.rs"

[[example]]
name = "event"
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_asset/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ filesystem_watcher = ["notify"]
[dependencies]
# bevy
bevy_app = { path = "../bevy_app", version = "0.4.0" }
bevy_diagnostic = { path = "../bevy_diagnostic", version = "0.4.0" }
bevy_ecs = { path = "../bevy_ecs", version = "0.4.0" }
bevy_reflect = { path = "../bevy_reflect", version = "0.4.0", features = ["bevy"] }
bevy_tasks = { path = "../bevy_tasks", version = "0.4.0" }
Expand Down
35 changes: 35 additions & 0 deletions crates/bevy_asset/src/diagnostic/asset_count_diagnostics_plugin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use crate::{Asset, Assets};
use bevy_app::prelude::*;
use bevy_diagnostic::{Diagnostic, DiagnosticId, Diagnostics};
use bevy_ecs::{IntoSystem, Res, ResMut};

/// Adds "asset count" diagnostic to an App
#[derive(Default)]
pub struct AssetCountDiagnosticsPlugin<T: Asset> {
marker: std::marker::PhantomData<T>,
}

impl<T: Asset> Plugin for AssetCountDiagnosticsPlugin<T> {
fn build(&self, app: &mut AppBuilder) {
app.add_startup_system(Self::setup_system.system())
.add_system(Self::diagnostic_system.system());
}
}

impl<T: Asset> AssetCountDiagnosticsPlugin<T> {
pub fn diagnostic_id() -> DiagnosticId {
DiagnosticId(T::TYPE_UUID)
}

pub fn setup_system(mut diagnostics: ResMut<Diagnostics>) {
diagnostics.add(Diagnostic::new(
Self::diagnostic_id(),
&format!("asset_count {}", std::any::type_name::<T>()),
20,
));
}

pub fn diagnostic_system(mut diagnostics: ResMut<Diagnostics>, assets: Res<Assets<T>>) {
diagnostics.add_measurement(Self::diagnostic_id(), assets.len() as f64);
}
}
2 changes: 2 additions & 0 deletions crates/bevy_asset/src/diagnostic/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
mod asset_count_diagnostics_plugin;
pub use asset_count_diagnostics_plugin::AssetCountDiagnosticsPlugin;
1 change: 1 addition & 0 deletions crates/bevy_asset/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod asset_server;
mod assets;
pub mod diagnostic;
#[cfg(all(
feature = "filesystem_watcher",
all(not(target_arch = "wasm32"), not(target_os = "android"))
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_diagnostic/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ keywords = ["bevy"]
bevy_app = { path = "../bevy_app", version = "0.4.0" }
bevy_core = { path = "../bevy_core", version = "0.4.0" }
bevy_ecs = { path = "../bevy_ecs", version = "0.4.0" }
bevy_log = { path = "../bevy_log", version = "0.4.0" }
bevy_utils = { path = "../bevy_utils", version = "0.4.0" }

# other
Expand Down
12 changes: 10 additions & 2 deletions crates/bevy_diagnostic/src/diagnostic.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use bevy_utils::{Duration, HashMap, Instant, Uuid};
use std::collections::VecDeque;
use std::collections::{BTreeSet, VecDeque};

/// Unique identifier for a [Diagnostic]
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, PartialOrd, Ord)]
pub struct DiagnosticId(pub Uuid);

impl DiagnosticId {
Expand Down Expand Up @@ -102,10 +102,12 @@ impl Diagnostic {
#[derive(Debug, Default)]
pub struct Diagnostics {
diagnostics: HashMap<DiagnosticId, Diagnostic>,
ordered_diagnostics: BTreeSet<DiagnosticId>,
}

impl Diagnostics {
pub fn add(&mut self, diagnostic: Diagnostic) {
self.ordered_diagnostics.insert(diagnostic.id);
self.diagnostics.insert(diagnostic.id, diagnostic);
}

Expand All @@ -132,4 +134,10 @@ impl Diagnostics {
pub fn iter(&self) -> impl Iterator<Item = &Diagnostic> {
self.diagnostics.values()
}

pub fn ordered_iter(&self) -> impl Iterator<Item = &Diagnostic> {
self.ordered_diagnostics
.iter()
.filter_map(move |k| self.diagnostics.get(k))
}
}
29 changes: 29 additions & 0 deletions crates/bevy_diagnostic/src/entity_count_diagnostics_plugin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use crate::{Diagnostic, DiagnosticId, Diagnostics};
use bevy_app::prelude::*;
use bevy_ecs::{IntoSystem, ResMut, Resources, World};

/// Adds "entity count" diagnostic to an App
#[derive(Default)]
pub struct EntityCountDiagnosticsPlugin;

impl Plugin for EntityCountDiagnosticsPlugin {
fn build(&self, app: &mut AppBuilder) {
app.add_startup_system(Self::setup_system.system())
.add_system(Self::diagnostic_system.system());
}
}

impl EntityCountDiagnosticsPlugin {
pub const ENTITY_COUNT: DiagnosticId =
DiagnosticId::from_u128(187513512115068938494459732780662867798);

pub fn setup_system(mut diagnostics: ResMut<Diagnostics>) {
diagnostics.add(Diagnostic::new(Self::ENTITY_COUNT, "entity_count", 20));
}

pub fn diagnostic_system(world: &mut World, resources: &mut Resources) {
if let Some(mut diagnostics) = resources.get_mut::<Diagnostics>() {
diagnostics.add_measurement(Self::ENTITY_COUNT, world.entity_count() as f64);
}
}
}
6 changes: 4 additions & 2 deletions crates/bevy_diagnostic/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
mod diagnostic;
mod entity_count_diagnostics_plugin;
mod frame_time_diagnostics_plugin;
mod print_diagnostics_plugin;
mod log_diagnostics_plugin;
pub use diagnostic::*;
pub use entity_count_diagnostics_plugin::EntityCountDiagnosticsPlugin;
pub use frame_time_diagnostics_plugin::FrameTimeDiagnosticsPlugin;
pub use print_diagnostics_plugin::PrintDiagnosticsPlugin;
pub use log_diagnostics_plugin::LogDiagnosticsPlugin;

use bevy_app::prelude::*;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,103 +2,102 @@ use super::{Diagnostic, DiagnosticId, Diagnostics};
use bevy_app::prelude::*;
use bevy_core::{Time, Timer};
use bevy_ecs::{IntoSystem, Res, ResMut};
use bevy_log::{debug, info};
use bevy_utils::Duration;

/// An App Plugin that prints diagnostics to the console
pub struct PrintDiagnosticsPlugin {
/// An App Plugin that logs diagnostics to the console
pub struct LogDiagnosticsPlugin {
pub debug: bool,
pub wait_duration: Duration,
pub filter: Option<Vec<DiagnosticId>>,
}

/// State used by the [PrintDiagnosticsPlugin]
pub struct PrintDiagnosticsState {
/// State used by the [LogDiagnosticsPlugin]
struct LogDiagnosticsState {
timer: Timer,
filter: Option<Vec<DiagnosticId>>,
}

impl Default for PrintDiagnosticsPlugin {
impl Default for LogDiagnosticsPlugin {
fn default() -> Self {
PrintDiagnosticsPlugin {
LogDiagnosticsPlugin {
debug: false,
wait_duration: Duration::from_secs(1),
filter: None,
}
}
}

impl Plugin for PrintDiagnosticsPlugin {
impl Plugin for LogDiagnosticsPlugin {
fn build(&self, app: &mut bevy_app::AppBuilder) {
app.add_resource(PrintDiagnosticsState {
app.add_resource(LogDiagnosticsState {
timer: Timer::new(self.wait_duration, true),
filter: self.filter.clone(),
});

if self.debug {
app.add_system_to_stage(
stage::POST_UPDATE,
Self::print_diagnostics_debug_system.system(),
Self::log_diagnostics_debug_system.system(),
);
} else {
app.add_system_to_stage(stage::POST_UPDATE, Self::print_diagnostics_system.system());
app.add_system_to_stage(stage::POST_UPDATE, Self::log_diagnostics_system.system());
}
}
}

impl PrintDiagnosticsPlugin {
impl LogDiagnosticsPlugin {
pub fn filtered(filter: Vec<DiagnosticId>) -> Self {
PrintDiagnosticsPlugin {
LogDiagnosticsPlugin {
filter: Some(filter),
..Default::default()
}
}

fn print_diagnostic(diagnostic: &Diagnostic) {
fn log_diagnostic(diagnostic: &Diagnostic) {
if let Some(value) = diagnostic.value() {
print!("{:<65}: {:<10.6}", diagnostic.name, value);
if let Some(average) = diagnostic.average() {
print!(" (avg {:.6})", average);
info!(
"{:<65}: {:<10.6} (avg {:.6})",
diagnostic.name, value, average
);
} else {
info!("{:<65}: {:<10.6}", diagnostic.name, value);
}

println!("\n");
}
}

pub fn print_diagnostics_system(
mut state: ResMut<PrintDiagnosticsState>,
fn log_diagnostics_system(
mut state: ResMut<LogDiagnosticsState>,
time: Res<Time>,
diagnostics: Res<Diagnostics>,
) {
if state.timer.tick(time.delta_seconds()).finished() {
println!("Diagnostics:");
println!("{}", "-".repeat(93));
if let Some(ref filter) = state.filter {
for diagnostic in filter.iter().map(|id| diagnostics.get(*id).unwrap()) {
Self::print_diagnostic(diagnostic);
Self::log_diagnostic(diagnostic);
}
} else {
for diagnostic in diagnostics.iter() {
Self::print_diagnostic(diagnostic);
for diagnostic in diagnostics.ordered_iter() {
Self::log_diagnostic(diagnostic);
}
}
}
}

pub fn print_diagnostics_debug_system(
mut state: ResMut<PrintDiagnosticsState>,
fn log_diagnostics_debug_system(
mut state: ResMut<LogDiagnosticsState>,
time: Res<Time>,
diagnostics: Res<Diagnostics>,
) {
if state.timer.tick(time.delta_seconds()).finished() {
println!("Diagnostics (Debug):");
println!("{}", "-".repeat(93));
if let Some(ref filter) = state.filter {
for diagnostic in filter.iter().map(|id| diagnostics.get(*id).unwrap()) {
println!("{:#?}\n", diagnostic);
debug!("{:#?}\n", diagnostic);
}
} else {
for diagnostic in diagnostics.iter() {
println!("{:#?}\n", diagnostic);
for diagnostic in diagnostics.ordered_iter() {
debug!("{:#?}\n", diagnostic);
}
}
}
Expand Down
11 changes: 11 additions & 0 deletions crates/bevy_ecs/src/core/entities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,9 +252,20 @@ impl Entities {
}
}

/// Number of freed entities in `self.meta`
pub fn freed_len(&self) -> u32 {
self.free_cursor.load(Ordering::Relaxed)
}

/// Number of reserved entities outside of `self.meta`
pub fn pending_len(&self) -> u32 {
self.pending.load(Ordering::Relaxed)
}

// The following three methods allow iteration over `reserved` simultaneous to location
// writes. This is a lazy hack, but we only use it in `World::flush` so the complexity and unsafety
// involved in producing an `impl Iterator<Item=(u32, &mut Location)>` isn't a clear win.
/// Number of reserved entities in `self.meta`
pub fn reserved_len(&self) -> u32 {
self.reserved_cursor.load(Ordering::Relaxed)
}
Expand Down
6 changes: 6 additions & 0 deletions crates/bevy_ecs/src/core/world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,12 @@ impl World {
})
}

pub fn entity_count(&self) -> u32 {
self.entities.meta.len() as u32 - self.entities.freed_len()
+ self.entities.reserved_len()
+ self.entities.pending_len()
}

/// Borrow the `T` component of `entity` without checking if it can be mutated
///
/// # Safety
Expand Down
4 changes: 2 additions & 2 deletions examples/3d/spawner.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use bevy::{
diagnostic::{FrameTimeDiagnosticsPlugin, PrintDiagnosticsPlugin},
diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin},
prelude::*,
};
use rand::{rngs::StdRng, Rng, SeedableRng};
Expand All @@ -12,7 +12,7 @@ fn main() {
App::build()
.add_plugins(DefaultPlugins)
.add_plugin(FrameTimeDiagnosticsPlugin::default())
.add_plugin(PrintDiagnosticsPlugin::default())
.add_plugin(LogDiagnosticsPlugin::default())
.add_startup_system(setup.system())
.add_system(move_cubes.system())
.run();
Expand Down
2 changes: 1 addition & 1 deletion examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ Example | File | Description
Example | File | Description
--- | --- | ---
`custom_diagnostic` | [`diagnostics/custom_diagnostic.rs`](./diagnostics/custom_diagnostic.rs) | Shows how to create a custom diagnostic
`print_diagnostics` | [`diagnostics/print_diagnostics.rs`](./diagnostics/print_diagnostics.rs) | Add a plugin that prints diagnostics to the console
`log_diagnostics` | [`diagnostics/log_diagnostics.rs`](./diagnostics/log_diagnostics.rs) | Add a plugin that logs diagnostics to the console

## ECS (Entity Component System)

Expand Down
2 changes: 1 addition & 1 deletion examples/app/plugin_group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fn main() {
// .add_plugins_with(HelloWorldPlugins, |group| {
// group
// .disable::<PrintWorldPlugin>()
// .add_before::<PrintHelloPlugin, _>(bevy::diagnostic::PrintDiagnosticsPlugin::default())
// .add_before::<PrintHelloPlugin, _>(bevy::diagnostic::LogDiagnosticsPlugin::default())
// })
.run();
}
Expand Down
4 changes: 2 additions & 2 deletions examples/diagnostics/custom_diagnostic.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use bevy::{
diagnostic::{Diagnostic, DiagnosticId, Diagnostics, PrintDiagnosticsPlugin},
diagnostic::{Diagnostic, DiagnosticId, Diagnostics, LogDiagnosticsPlugin},
prelude::*,
};

Expand All @@ -8,7 +8,7 @@ fn main() {
App::build()
.add_plugins(DefaultPlugins)
// The "print diagnostics" plugin is optional. It just visualizes our diagnostics in the console
.add_plugin(PrintDiagnosticsPlugin::default())
.add_plugin(LogDiagnosticsPlugin::default())
.add_startup_system(setup_diagnostic_system.system())
.add_system(my_system.system())
.run();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use bevy::{
diagnostic::{FrameTimeDiagnosticsPlugin, PrintDiagnosticsPlugin},
diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin},
prelude::*,
};

Expand All @@ -9,9 +9,13 @@ fn main() {
// Adds frame time diagnostics
.add_plugin(FrameTimeDiagnosticsPlugin::default())
// Adds a system that prints diagnostics to the console
.add_plugin(PrintDiagnosticsPlugin::default())
.add_plugin(LogDiagnosticsPlugin::default())
// Any plugin can register diagnostics
// Uncomment this to add some render resource diagnostics:
// .add_plugin(bevy::wgpu::diagnostic::WgpuResourceDiagnosticsPlugin::default())
// Uncomment this to add an entity count diagnostics:
// .add_plugin(bevy::diagnostic::EntityCountDiagnosticsPlugin::default())
// Uncomment this to add an asset count diagnostics:
// .add_plugin(bevy::asset::diagnostic::AssetCountDiagnosticsPlugin::<Texture>::default())
.run();
}