use std::time::{Duration, Instant};
#[macro_export]
macro_rules! time_block {
($name:expr, $body:block) => {{
let _timer = $crate::ScopedTimer::new($name);
let __td_result = (|| $body )();
__td_result
}};
}
#[allow(dead_code)]
fn format_duration(nanos: f64) -> String {
if nanos < 1_000.0 {
format!("{nanos:.2} ns")
} else if nanos < 100_000.0 {
format!("{:.2} us", nanos / 1_000.0)
} else if nanos < 1_000_000_000.0 {
format!("{:.2} ms", nanos / 1_000_000.0)
} else {
format!("{:.2} s", nanos / 1_000_000_000.0)
}
}
pub enum Grade {
Great,
Good,
Warning,
Bad,
}
#[cfg(feature = "enable_summary")]
fn grade_from_nano(nanos: f64) -> Grade {
let ms = (nanos / 1_000_000.0) as u64;
if ms < 10 {
Grade::Great
} else if ms < 40 {
Grade::Good
} else if ms < 70 {
Grade::Warning
} else {
Grade::Bad
}
}
#[cfg(feature = "enable_summary")]
const RESET: &str = "\x1B[0m";
#[cfg(feature = "enable_summary")]
const RED: &str = "\x1B[31m";
#[cfg(feature = "enable_summary")]
const GREEN: &str = "\x1B[32m";
#[cfg(feature = "enable_summary")]
const YELLOW_BOLD: &str = "\x1B[1;33m";
#[cfg(feature = "enable_summary")]
const CYAN: &str = "\x1B[36m";
#[cfg(feature = "enable_summary")]
const BLUE: &str = "\x1B[34m";
#[cfg(feature = "enable_summary")]
pub fn summary(name: &str, total_execution_time: Duration) {
let duration = total_execution_time;
let total_nanos = duration.as_nanos() as f64;
let grade = grade_from_nano(total_nanos);
let grade_color_string = match grade {
Grade::Great => GREEN,
Grade::Good => CYAN,
Grade::Warning => YELLOW_BOLD,
Grade::Bad => RED,
};
eprintln!(
"timer '{}{}{}' completed in {}{}{}",
BLUE,
name,
RESET,
grade_color_string,
format_duration(total_nanos),
RESET,
);
}
#[derive(Debug)]
pub struct ScopedTimer<'a> {
start: Instant,
#[allow(dead_code)]
name: &'a str,
}
impl<'a> ScopedTimer<'a> {
#[must_use]
pub fn new(name: &'a str) -> Self {
Self {
start: Instant::now(),
name,
}
}
#[must_use]
pub fn elapsed(&self) -> Duration {
self.start.elapsed()
}
}
impl Drop for ScopedTimer<'_> {
fn drop(&mut self) {
#[cfg(feature = "enable_summary")]
{
let elapsed = self.start.elapsed();
summary(self.name, elapsed);
}
}
}