gravel_core/
performance.rs

1use log::Level;
2use std::fmt::{self, Arguments, Display, Formatter};
3use std::time::Instant;
4
5#[derive(Debug)]
6pub struct Stopwatch {
7	begin: Instant,
8}
9
10impl Stopwatch {
11	pub fn start() -> Self {
12		Self { begin: Instant::now() }
13	}
14}
15
16impl Display for Stopwatch {
17	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
18		// convert micros -> millis so we get decimal values
19		let micros = self.begin.elapsed().as_micros() as f32;
20		let millis = micros / 1000.0;
21		write!(f, "{millis}ms")
22	}
23}
24
25#[derive(Debug)]
26pub struct Timed {
27	message: String,
28	level: Level,
29	stopwatch: Stopwatch,
30}
31
32impl Timed {
33	pub fn new(level: Level, args: Arguments<'_>) -> Option<Self> {
34		if level > log::STATIC_MAX_LEVEL || level > log::max_level() {
35			return None;
36		}
37
38		Some(Self {
39			message: args.to_string(),
40			level,
41			stopwatch: Stopwatch::start(),
42		})
43	}
44}
45
46impl Drop for Timed {
47	fn drop(&mut self) {
48		log::log!(self.level, "{} {}", self.message, self.stopwatch);
49	}
50}
51
52#[macro_export]
53macro_rules! timed {
54	( ($($arg:tt)*), $body:block ) => { timed!(::log::Level::Trace, ::std::format_args!($($arg)*), $body) };
55	( $msg:literal, $body:block ) => { timed!(::log::Level::Trace, ::std::format_args!($msg), $body) };
56	( $level:expr, ($($arg:tt)*), $body:block ) => { timed!($level, ::std::format_args!($($arg)*), $body) };
57	( $level:expr, $msg:literal, $body:block ) => { timed!($level, ::std::format_args!($msg), $body) };
58
59	( $level:expr, $msg:expr, $body:block ) => {{
60		let __time = $crate::performance::Timed::new($level, $msg);
61
62		$body
63	}};
64}