rapier3d/counters/
mod.rs

1//! Counters for benchmarking various parts of the physics engine.
2
3use core::time::Duration;
4use std::fmt::{Display, Formatter, Result};
5
6pub use self::ccd_counters::CCDCounters;
7pub use self::collision_detection_counters::CollisionDetectionCounters;
8pub use self::solver_counters::SolverCounters;
9pub use self::stages_counters::StagesCounters;
10pub use self::timer::Timer;
11
12mod ccd_counters;
13mod collision_detection_counters;
14mod solver_counters;
15mod stages_counters;
16mod timer;
17
18/// Aggregation of all the performances counters tracked by rapier.
19#[derive(Clone, Copy)]
20pub struct Counters {
21    /// Whether this counter is enabled or not.
22    pub enabled: bool,
23    /// Timer for a whole timestep.
24    pub step_time: Timer,
25    /// Timer used for debugging.
26    pub custom: Timer,
27    /// Counters of every stage of one time step.
28    pub stages: StagesCounters,
29    /// Counters of the collision-detection stage.
30    pub cd: CollisionDetectionCounters,
31    /// Counters of the constraints resolution and force computation stage.
32    pub solver: SolverCounters,
33    /// Counters for the CCD resolution stage.
34    pub ccd: CCDCounters,
35}
36
37impl Counters {
38    /// Create a new set of counters initialized to zero.
39    pub fn new(enabled: bool) -> Self {
40        Counters {
41            enabled,
42            step_time: Timer::new(),
43            custom: Timer::new(),
44            stages: StagesCounters::new(),
45            cd: CollisionDetectionCounters::new(),
46            solver: SolverCounters::new(),
47            ccd: CCDCounters::new(),
48        }
49    }
50
51    /// Enable all the counters.
52    pub fn enable(&mut self) {
53        self.enabled = true;
54    }
55
56    /// Return `true` if the counters are enabled.
57    pub fn enabled(&self) -> bool {
58        self.enabled
59    }
60
61    /// Disable all the counters.
62    pub fn disable(&mut self) {
63        self.enabled = false;
64    }
65
66    /// Notify that the time-step has started.
67    pub fn step_started(&mut self) {
68        if self.enabled {
69            self.step_time.start();
70        }
71    }
72
73    /// Notify that the time-step has finished.
74    pub fn step_completed(&mut self) {
75        if self.enabled {
76            self.step_time.pause();
77        }
78    }
79
80    /// Total time spent for one of the physics engine.
81    pub fn step_time(&self) -> Duration {
82        self.step_time.time()
83    }
84
85    /// Total time spent for one of the physics engine, in milliseconds.
86    pub fn step_time_ms(&self) -> f64 {
87        self.step_time.time_ms()
88    }
89
90    /// Notify that the custom operation has started.
91    pub fn custom_started(&mut self) {
92        if self.enabled {
93            self.custom.start();
94        }
95    }
96
97    /// Notify that the custom operation has finished.
98    pub fn custom_completed(&mut self) {
99        if self.enabled {
100            self.custom.pause();
101        }
102    }
103
104    /// Total time of a custom event.
105    pub fn custom_time(&self) -> Duration {
106        self.custom.time()
107    }
108
109    /// Total time of a custom event, in milliseconds.
110    pub fn custom_time_ms(&self) -> f64 {
111        self.custom.time_ms()
112    }
113
114    /// Set the number of constraints generated.
115    pub fn set_nconstraints(&mut self, n: usize) {
116        self.solver.nconstraints = n;
117    }
118
119    /// Set the number of contacts generated.
120    pub fn set_ncontacts(&mut self, n: usize) {
121        self.solver.ncontacts = n;
122    }
123
124    /// Set the number of contact pairs generated.
125    pub fn set_ncontact_pairs(&mut self, n: usize) {
126        self.cd.ncontact_pairs = n;
127    }
128
129    /// Resets all the counters and timers.
130    pub fn reset(&mut self) {
131        if self.enabled {
132            self.step_time.reset();
133            self.custom.reset();
134            self.stages.reset();
135            self.cd.reset();
136            self.solver.reset();
137            self.ccd.reset();
138        }
139    }
140}
141
142macro_rules! measure_method {
143    ($started:ident, $stopped:ident, $time_ms:ident, $info:ident. $timer:ident) => {
144        impl Counters {
145            /// Start this timer.
146            pub fn $started(&mut self) {
147                if self.enabled {
148                    self.$info.$timer.start()
149                }
150            }
151
152            /// Stop this timer.
153            pub fn $stopped(&mut self) {
154                if self.enabled {
155                    self.$info.$timer.pause()
156                }
157            }
158
159            /// Gets the time elapsed for this timer, in milliseconds.
160            pub fn $time_ms(&self) -> f64 {
161                if self.enabled {
162                    self.$info.$timer.time_ms()
163                } else {
164                    0.0
165                }
166            }
167        }
168    };
169}
170
171measure_method!(
172    update_started,
173    update_completed,
174    update_time_ms,
175    stages.update_time
176);
177measure_method!(
178    collision_detection_started,
179    collision_detection_completed,
180    collision_detection_time_ms,
181    stages.collision_detection_time
182);
183measure_method!(
184    island_construction_started,
185    island_construction_completed,
186    island_construction_time_ms,
187    stages.island_construction_time
188);
189measure_method!(
190    solver_started,
191    solver_completed,
192    solver_time_ms,
193    stages.solver_time
194);
195measure_method!(ccd_started, ccd_completed, ccd_time_ms, stages.ccd_time);
196
197measure_method!(
198    assembly_started,
199    assembly_completed,
200    assembly_time_ms,
201    solver.velocity_assembly_time
202);
203measure_method!(
204    velocity_resolution_started,
205    velocity_resolution_completed,
206    velocity_resolution_time_ms,
207    solver.velocity_resolution_time
208);
209measure_method!(
210    velocity_update_started,
211    velocity_update_completed,
212    velocity_update_time_ms,
213    solver.velocity_update_time
214);
215measure_method!(
216    broad_phase_started,
217    broad_phase_completed,
218    broad_phase_time_ms,
219    cd.broad_phase_time
220);
221measure_method!(
222    narrow_phase_started,
223    narrow_phase_completed,
224    narrow_phase_time_ms,
225    cd.narrow_phase_time
226);
227
228impl Display for Counters {
229    fn fmt(&self, f: &mut Formatter) -> Result {
230        writeln!(f, "Total timestep time: {}", self.step_time)?;
231        self.stages.fmt(f)?;
232        self.cd.fmt(f)?;
233        self.solver.fmt(f)?;
234        writeln!(f, "Custom timer: {}", self.custom)
235    }
236}
237
238impl Default for Counters {
239    fn default() -> Self {
240        Self::new(false)
241    }
242}