amaters_core/
profiling.rs1use std::sync::atomic::{AtomicU64, Ordering};
4use std::time::{Duration, Instant};
5
6pub static ALLOC_COUNT: AtomicU64 = AtomicU64::new(0);
8
9pub static ALLOC_BYTES: AtomicU64 = AtomicU64::new(0);
11
12pub struct ProfilingGuard {
14 name: &'static str,
15 start: Instant,
16}
17
18impl ProfilingGuard {
19 pub fn new(name: &'static str) -> Self {
32 Self {
33 name,
34 start: Instant::now(),
35 }
36 }
37
38 pub fn elapsed(&self) -> Duration {
40 self.start.elapsed()
41 }
42
43 pub fn finish(self) -> ProfilingSummary {
45 let elapsed = self.elapsed();
46 let alloc_count_delta = ALLOC_COUNT.load(Ordering::Relaxed);
47 let alloc_bytes_delta = ALLOC_BYTES.load(Ordering::Relaxed);
48
49 tracing::debug!(
50 target: "amaters::profiling",
51 name = self.name,
52 elapsed_us = elapsed.as_micros() as u64,
53 alloc_count = alloc_count_delta,
54 alloc_bytes = alloc_bytes_delta,
55 "profiling guard finished"
56 );
57
58 let name = self.name;
59 std::mem::forget(self);
61
62 ProfilingSummary {
63 name,
64 elapsed,
65 alloc_count_delta,
66 alloc_bytes_delta,
67 }
68 }
69}
70
71impl Drop for ProfilingGuard {
72 fn drop(&mut self) {
73 tracing::debug!(
74 target: "amaters::profiling",
75 name = self.name,
76 elapsed_us = self.elapsed().as_micros() as u64,
77 "profiling guard dropped"
78 );
79 }
80}
81
82#[derive(Debug, Clone)]
84pub struct ProfilingSummary {
85 pub name: &'static str,
87 pub elapsed: Duration,
89 pub alloc_count_delta: u64,
91 pub alloc_bytes_delta: u64,
93}
94
95#[cfg(test)]
96mod tests {
97 use super::*;
98 use std::thread;
99
100 #[test]
101 fn test_profiling_guard_measures_elapsed() {
102 let guard = ProfilingGuard::new("test_op");
103 thread::sleep(Duration::from_millis(5));
104 let elapsed = guard.elapsed();
105 assert!(elapsed >= Duration::from_millis(1), "elapsed: {elapsed:?}");
106 drop(guard);
107 }
108
109 #[test]
110 fn test_profiling_summary_has_valid_duration() {
111 let guard = ProfilingGuard::new("summary_op");
112 thread::sleep(Duration::from_millis(2));
113 let summary = guard.finish();
114 assert_eq!(summary.name, "summary_op");
115 assert!(
116 summary.elapsed >= Duration::from_millis(1),
117 "elapsed: {:?}",
118 summary.elapsed
119 );
120 }
121
122 #[test]
123 fn test_profiling_guard_drop_does_not_panic() {
124 let guard = ProfilingGuard::new("drop_test");
125 drop(guard);
126 }
127}