chj_util/
time_guard.rs

1//! # Tools for performance debugging.
2
3//! `time!` is currently always enabled. `time_guard!` is only enabled
4//! if the `TIME_GUARD` env var is set to a truthy value or
5//! `enabled_set(true)` was called in the thread.
6
7//! `time!` and `time_guard!` can also be statically disabled
8//! (compiled out completely) by prefixing their names with `no`.
9
10use std::{time::Instant, fmt::Debug, cell::Cell, os::unix::prelude::OsStrExt};
11
12fn time_guard_env_get() -> bool {
13    match std::env::var_os("TIME_GUARD") {
14        Some(v) => match v.as_bytes() {
15            b"0" | b"" | b"off" | b"false" | b"no" => false,
16            _ => true
17        }
18        None => false
19    }
20}
21
22thread_local!{
23    pub static ENABLED: Cell<bool> = Cell::new(time_guard_env_get());
24}
25
26/// Enable `time_guard!`.
27pub fn enabled_set(on: bool) {
28    ENABLED.with(|cell| cell.set(on))
29}
30
31pub fn enabled() -> bool {
32    ENABLED.with(|old| old.get())
33}
34
35
36// XX also enable/disable?
37#[macro_export]
38macro_rules! time {
39    ($name:expr; $($code:tt)*) => {{
40        let msg = format!("time {}", $name);
41        let now = std::time::Instant::now();
42        let r = {
43            $($code)*
44        };
45        let elapsed = now.elapsed();
46        eprintln!("{msg}: {elapsed:?} at {:?} line {}", file!(), line!());
47        r
48    }}
49}
50
51#[macro_export]
52macro_rules! notime {
53    ($name:expr; $($code:tt)*) => {{
54        $($code)*
55    }}
56}
57
58
59
60// Reminiscent of dt.rs (DtGuard)
61
62pub enum TimeGuard<S: Debug> {
63    Disabled,
64    Enabled {
65         name: S,
66        start: Instant
67    },
68}
69
70impl<S: Debug> Drop for TimeGuard<S> {
71    fn drop(&mut self) {
72        match self {
73            TimeGuard::Disabled => (),
74            TimeGuard::Enabled { name, start } => {
75                let elapsed = start.elapsed();
76                eprintln!("{:?}: {:#?}", name, elapsed);
77            },
78        }
79    }
80}
81
82#[macro_export]
83macro_rules! time_guard {
84    ($namestr:expr) => {
85        let _guard = if $crate::time_guard::enabled() {
86            $crate::time_guard::TimeGuard::Enabled {
87                name: $namestr,
88                start: std::time::Instant::now()
89            }
90        } else {
91            $crate::time_guard::TimeGuard::Disabled
92        };
93    }
94}
95
96#[macro_export]
97macro_rules! notime_guard {
98    ($namestr:expr) => {}
99}
100