|
5 | 5 | use core::fmt;
|
6 | 6 | use std::any::Any;
|
7 | 7 | use std::boxed::Box;
|
8 |
| -use std::cell::{Cell, RefCell}; |
| 8 | +use std::cell::RefCell; |
9 | 9 | use std::mem;
|
10 |
| -use std::time::{Duration, Instant}; |
| 10 | +use std::time::Duration; |
11 | 11 |
|
12 | 12 | // Each pass that can be timed is predefined with the `define_passes!` macro. Each pass has a
|
13 | 13 | // snake_case name and a plain text description used when printing out the timing report.
|
@@ -130,22 +130,6 @@ fn start_pass(pass: Pass) -> Box<dyn Any> {
|
130 | 130 | PROFILER.with(|profiler| profiler.borrow().start_pass(pass))
|
131 | 131 | }
|
132 | 132 |
|
133 |
| -/// A timing token is responsible for timing the currently running pass. Timing starts when it |
134 |
| -/// is created and ends when it is dropped. |
135 |
| -/// |
136 |
| -/// Multiple passes can be active at the same time, but they must be started and stopped in a |
137 |
| -/// LIFO fashion. |
138 |
| -struct DefaultTimingToken { |
139 |
| - /// Start time for this pass. |
140 |
| - start: Instant, |
141 |
| - |
142 |
| - // Pass being timed by this token. |
143 |
| - pass: Pass, |
144 |
| - |
145 |
| - // The previously active pass which will be restored when this token is dropped. |
146 |
| - prev: Pass, |
147 |
| -} |
148 |
| - |
149 | 133 | /// Accumulated timing information for a single pass.
|
150 | 134 | #[derive(Default, Copy, Clone)]
|
151 | 135 | struct PassTime {
|
@@ -215,49 +199,91 @@ impl fmt::Display for PassTimes {
|
215 | 199 |
|
216 | 200 | // Information about passes in a single thread.
|
217 | 201 | thread_local! {
|
218 |
| - static CURRENT_PASS: Cell<Pass> = const { Cell::new(Pass::None) }; |
219 | 202 | static PASS_TIME: RefCell<PassTimes> = RefCell::new(Default::default());
|
220 | 203 | }
|
221 | 204 |
|
222 | 205 | /// The default profiler. You can get the results using [`take_current`].
|
223 | 206 | pub struct DefaultProfiler;
|
224 | 207 |
|
225 |
| -impl Profiler for DefaultProfiler { |
226 |
| - fn start_pass(&self, pass: Pass) -> Box<dyn Any> { |
227 |
| - let prev = CURRENT_PASS.with(|p| p.replace(pass)); |
228 |
| - log::debug!("timing: Starting {}, (during {})", pass, prev); |
229 |
| - Box::new(DefaultTimingToken { |
230 |
| - start: Instant::now(), |
231 |
| - pass, |
232 |
| - prev, |
233 |
| - }) |
234 |
| - } |
235 |
| -} |
236 |
| - |
237 |
| -/// Dropping a timing token indicated the end of the pass. |
238 |
| -impl Drop for DefaultTimingToken { |
239 |
| - fn drop(&mut self) { |
240 |
| - let duration = self.start.elapsed(); |
241 |
| - log::debug!("timing: Ending {}: {}ms", self.pass, duration.as_millis()); |
242 |
| - let old_cur = CURRENT_PASS.with(|p| p.replace(self.prev)); |
243 |
| - debug_assert_eq!(self.pass, old_cur, "Timing tokens dropped out of order"); |
244 |
| - PASS_TIME.with(|rc| { |
245 |
| - let mut table = rc.borrow_mut(); |
246 |
| - table.pass[self.pass.idx()].total += duration; |
247 |
| - if let Some(parent) = table.pass.get_mut(self.prev.idx()) { |
248 |
| - parent.child += duration; |
249 |
| - } |
250 |
| - }) |
251 |
| - } |
252 |
| -} |
253 |
| - |
254 | 208 | /// Take the current accumulated pass timings and reset the timings for the current thread.
|
255 | 209 | ///
|
256 | 210 | /// Only applies when [`DefaultProfiler`] is used.
|
257 | 211 | pub fn take_current() -> PassTimes {
|
258 | 212 | PASS_TIME.with(|rc| mem::take(&mut *rc.borrow_mut()))
|
259 | 213 | }
|
260 | 214 |
|
| 215 | +#[cfg(feature = "timing")] |
| 216 | +mod enabled { |
| 217 | + use super::{DefaultProfiler, Pass, Profiler, PASS_TIME}; |
| 218 | + use std::any::Any; |
| 219 | + use std::boxed::Box; |
| 220 | + use std::cell::Cell; |
| 221 | + use std::time::Instant; |
| 222 | + |
| 223 | + // Information about passes in a single thread. |
| 224 | + thread_local! { |
| 225 | + static CURRENT_PASS: Cell<Pass> = const { Cell::new(Pass::None) }; |
| 226 | + } |
| 227 | + |
| 228 | + impl Profiler for DefaultProfiler { |
| 229 | + fn start_pass(&self, pass: Pass) -> Box<dyn Any> { |
| 230 | + let prev = CURRENT_PASS.with(|p| p.replace(pass)); |
| 231 | + log::debug!("timing: Starting {}, (during {})", pass, prev); |
| 232 | + Box::new(DefaultTimingToken { |
| 233 | + start: Instant::now(), |
| 234 | + pass, |
| 235 | + prev, |
| 236 | + }) |
| 237 | + } |
| 238 | + } |
| 239 | + |
| 240 | + /// A timing token is responsible for timing the currently running pass. Timing starts when it |
| 241 | + /// is created and ends when it is dropped. |
| 242 | + /// |
| 243 | + /// Multiple passes can be active at the same time, but they must be started and stopped in a |
| 244 | + /// LIFO fashion. |
| 245 | + struct DefaultTimingToken { |
| 246 | + /// Start time for this pass. |
| 247 | + start: Instant, |
| 248 | + |
| 249 | + // Pass being timed by this token. |
| 250 | + pass: Pass, |
| 251 | + |
| 252 | + // The previously active pass which will be restored when this token is dropped. |
| 253 | + prev: Pass, |
| 254 | + } |
| 255 | + |
| 256 | + /// Dropping a timing token indicated the end of the pass. |
| 257 | + impl Drop for DefaultTimingToken { |
| 258 | + fn drop(&mut self) { |
| 259 | + let duration = self.start.elapsed(); |
| 260 | + log::debug!("timing: Ending {}: {}ms", self.pass, duration.as_millis()); |
| 261 | + let old_cur = CURRENT_PASS.with(|p| p.replace(self.prev)); |
| 262 | + debug_assert_eq!(self.pass, old_cur, "Timing tokens dropped out of order"); |
| 263 | + PASS_TIME.with(|rc| { |
| 264 | + let mut table = rc.borrow_mut(); |
| 265 | + table.pass[self.pass.idx()].total += duration; |
| 266 | + if let Some(parent) = table.pass.get_mut(self.prev.idx()) { |
| 267 | + parent.child += duration; |
| 268 | + } |
| 269 | + }) |
| 270 | + } |
| 271 | + } |
| 272 | +} |
| 273 | + |
| 274 | +#[cfg(not(feature = "timing"))] |
| 275 | +mod disabled { |
| 276 | + use super::{DefaultProfiler, Pass, Profiler}; |
| 277 | + use std::any::Any; |
| 278 | + use std::boxed::Box; |
| 279 | + |
| 280 | + impl Profiler for DefaultProfiler { |
| 281 | + fn start_pass(&self, _pass: Pass) -> Box<dyn Any> { |
| 282 | + Box::new(()) |
| 283 | + } |
| 284 | + } |
| 285 | +} |
| 286 | + |
261 | 287 | #[cfg(test)]
|
262 | 288 | mod tests {
|
263 | 289 | use super::*;
|
|
0 commit comments