vibesql/
profiling.rs

1//! Performance profiling utilities for benchmarking
2//!
3//! This module provides timing instrumentation to understand performance bottlenecks
4//! when comparing vibesql with other databases like SQLite.
5
6use std::{
7    sync::atomic::{AtomicBool, Ordering},
8    time::Instant,
9};
10
11/// Global flag to enable/disable profiling (disabled by default)
12static PROFILING_ENABLED: AtomicBool = AtomicBool::new(false);
13
14/// Enable profiling (call before benchmarks)
15pub fn enable_profiling() {
16    PROFILING_ENABLED.store(true, Ordering::Relaxed);
17}
18
19/// Disable profiling
20pub fn disable_profiling() {
21    PROFILING_ENABLED.store(false, Ordering::Relaxed);
22}
23
24/// Check if profiling is enabled
25pub fn is_profiling_enabled() -> bool {
26    PROFILING_ENABLED.load(Ordering::Relaxed)
27}
28
29/// A profiling timer that logs elapsed time when dropped
30#[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    /// Create a new profiling timer
40    pub fn new(label: &'static str) -> Self {
41        let enabled = is_profiling_enabled();
42        Self { label, start: Instant::now(), enabled }
43    }
44
45    /// Manually stop the timer and log (useful for conditional logic)
46    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 to create a profiling scope
66#[macro_export]
67macro_rules! profile {
68    ($label:expr) => {
69        let _timer = $crate::profiling::ProfileTimer::new($label);
70    };
71}
72
73/// Profile a section of code with detailed sub-timings
74pub 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    /// Log a checkpoint with time since last checkpoint and total time
92    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}