//! Counters for benchmarking various parts of the physics engine. use std::fmt::{Display, Formatter, Result}; pub use self::ccd_counters::CCDCounters; pub use self::collision_detection_counters::CollisionDetectionCounters; pub use self::solver_counters::SolverCounters; pub use self::stages_counters::StagesCounters; pub use self::timer::Timer; mod ccd_counters; mod collision_detection_counters; mod solver_counters; mod stages_counters; mod timer; /// Aggregation of all the performances counters tracked by nphysics. #[derive(Clone, Copy)] pub struct Counters { /// Whether thi counter is enabled or not. pub enabled: bool, /// Timer for a whole timestep. pub step_time: Timer, /// Timer used for debugging. pub custom: Timer, /// Counters of every satge of one time step. pub stages: StagesCounters, /// Counters of the collision-detection stage. pub cd: CollisionDetectionCounters, /// Counters of the constraints resolution and force computation stage. pub solver: SolverCounters, /// Counters for the CCD resolution stage. pub ccd: CCDCounters, } impl Counters { /// Create a new set of counters initialized to wero. pub fn new(enabled: bool) -> Self { Counters { enabled, step_time: Timer::new(), custom: Timer::new(), stages: StagesCounters::new(), cd: CollisionDetectionCounters::new(), solver: SolverCounters::new(), ccd: CCDCounters::new(), } } /// Enable all the counters. pub fn enable(&mut self) { self.enabled = true; } /// Return `true` if the counters are enabled. pub fn enabled(&self) -> bool { self.enabled } /// Disable all the counters. pub fn disable(&mut self) { self.enabled = false; } /// Notify that the time-step has started. pub fn step_started(&mut self) { if self.enabled { self.step_time.start(); } } /// Notfy that the time-step has finished. pub fn step_completed(&mut self) { if self.enabled { self.step_time.pause(); } } /// Total time spent for one of the physics engine. pub fn step_time(&self) -> f64 { self.step_time.time() } /// Notify that the custom operation has started. pub fn custom_started(&mut self) { if self.enabled { self.custom.start(); } } /// Notfy that the custom operation has finished. pub fn custom_completed(&mut self) { if self.enabled { self.custom.pause(); } } /// Total time of a custom event. pub fn custom_time(&self) -> f64 { self.custom.time() } /// Set the number of constraints generated. pub fn set_nconstraints(&mut self, n: usize) { self.solver.nconstraints = n; } /// Set the number of contacts generated. pub fn set_ncontacts(&mut self, n: usize) { self.solver.ncontacts = n; } /// Set the number of contact pairs generated. pub fn set_ncontact_pairs(&mut self, n: usize) { self.cd.ncontact_pairs = n; } /// Resets all the counters and timers. pub fn reset(&mut self) { if self.enabled { self.step_time.reset(); self.custom.reset(); self.stages.reset(); self.cd.reset(); self.solver.reset(); self.ccd.reset(); } } } macro_rules! measure_method { ($started:ident, $stopped:ident, $time:ident, $info:ident. $timer:ident) => { impl Counters { /// Start this timer. pub fn $started(&mut self) { if self.enabled { self.$info.$timer.start() } } /// Stop this timer. pub fn $stopped(&mut self) { if self.enabled { self.$info.$timer.pause() } } /// Gets the time elapsed for this timer. pub fn $time(&self) -> f64 { if self.enabled { self.$info.$timer.time() } else { 0.0 } } } }; } measure_method!( update_started, update_completed, update_time, stages.update_time ); measure_method!( collision_detection_started, collision_detection_completed, collision_detection_time, stages.collision_detection_time ); measure_method!( island_construction_started, island_construction_completed, island_construction_time, stages.island_construction_time ); measure_method!( solver_started, solver_completed, solver_time, stages.solver_time ); measure_method!(ccd_started, ccd_completed, ccd_time, stages.ccd_time); measure_method!( assembly_started, assembly_completed, assembly_time, solver.velocity_assembly_time ); measure_method!( velocity_resolution_started, velocity_resolution_completed, velocity_resolution_time, solver.velocity_resolution_time ); measure_method!( velocity_update_started, velocity_update_completed, velocity_update_time, solver.velocity_update_time ); measure_method!( position_resolution_started, position_resolution_completed, position_resolution_time, solver.position_resolution_time ); measure_method!( broad_phase_started, broad_phase_completed, broad_phase_time, cd.broad_phase_time ); measure_method!( narrow_phase_started, narrow_phase_completed, narrow_phase_time, cd.narrow_phase_time ); impl Display for Counters { fn fmt(&self, f: &mut Formatter) -> Result { writeln!(f, "Total timestep time: {}", self.step_time)?; self.stages.fmt(f)?; self.cd.fmt(f)?; self.solver.fmt(f)?; writeln!(f, "Custom timer: {}", self.custom) } } impl Default for Counters { fn default() -> Self { Self::new(false) } }