1use std::{
7 sync::atomic::{AtomicBool, Ordering},
8 time::Instant,
9};
10
11static PROFILING_ENABLED: AtomicBool = AtomicBool::new(false);
13
14pub fn enable_profiling() {
16 PROFILING_ENABLED.store(true, Ordering::Relaxed);
17}
18
19pub fn disable_profiling() {
21 PROFILING_ENABLED.store(false, Ordering::Relaxed);
22}
23
24pub fn is_profiling_enabled() -> bool {
26 PROFILING_ENABLED.load(Ordering::Relaxed)
27}
28
29#[allow(dead_code)]
31pub struct ProfileTimer {
32 label: &'static str,
33 start: Instant,
34 enabled: bool,
35}
36
37#[allow(dead_code)]
38impl ProfileTimer {
39 pub fn new(label: &'static str) -> Self {
41 let enabled = is_profiling_enabled();
42 Self { label, start: Instant::now(), enabled }
43 }
44
45 pub fn stop(self) {
47 drop(self);
48 }
49}
50
51impl Drop for ProfileTimer {
52 fn drop(&mut self) {
53 if self.enabled {
54 let elapsed = self.start.elapsed();
55 eprintln!(
56 "[PROFILE] {} took {:.3}ms ({:.0}µs)",
57 self.label,
58 elapsed.as_secs_f64() * 1000.0,
59 elapsed.as_micros()
60 );
61 }
62 }
63}
64
65#[macro_export]
67macro_rules! profile {
68 ($label:expr) => {
69 let _timer = $crate::profiling::ProfileTimer::new($label);
70 };
71}
72
73pub struct DetailedProfiler {
75 operation: &'static str,
76 start: Instant,
77 enabled: bool,
78 last_checkpoint: Instant,
79}
80
81impl DetailedProfiler {
82 pub fn new(operation: &'static str) -> Self {
83 let enabled = is_profiling_enabled();
84 let now = Instant::now();
85 if enabled {
86 eprintln!("[PROFILE] === Starting: {} ===", operation);
87 }
88 Self { operation, start: now, enabled, last_checkpoint: now }
89 }
90
91 pub fn checkpoint(&mut self, label: &str) {
93 if self.enabled {
94 let now = Instant::now();
95 let delta = now.duration_since(self.last_checkpoint);
96 let total = now.duration_since(self.start);
97 eprintln!(
98 "[PROFILE] {} | delta: {:.3}ms | total: {:.3}ms",
99 label,
100 delta.as_secs_f64() * 1000.0,
101 total.as_secs_f64() * 1000.0
102 );
103 self.last_checkpoint = now;
104 }
105 }
106}
107
108impl Drop for DetailedProfiler {
109 fn drop(&mut self) {
110 if self.enabled {
111 let total = self.start.elapsed();
112 eprintln!(
113 "[PROFILE] === Completed: {} in {:.3}ms ({:.0}µs) ===\n",
114 self.operation,
115 total.as_secs_f64() * 1000.0,
116 total.as_micros()
117 );
118 }
119 }
120}