use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Instant;
static PROFILING_ENABLED: AtomicBool = AtomicBool::new(false);
static MONITORING_ENABLED: AtomicBool = AtomicBool::new(false);
pub fn enable_profiling() {
PROFILING_ENABLED.store(true, Ordering::Relaxed);
}
pub fn disable_profiling() {
PROFILING_ENABLED.store(false, Ordering::Relaxed);
}
pub fn is_profiling_enabled() -> bool {
PROFILING_ENABLED.load(Ordering::Relaxed)
}
pub fn enable_monitoring() {
MONITORING_ENABLED.store(true, Ordering::Relaxed);
}
pub fn disable_monitoring() {
MONITORING_ENABLED.store(false, Ordering::Relaxed);
}
pub fn is_monitoring_enabled() -> bool {
MONITORING_ENABLED.load(Ordering::Relaxed)
}
pub struct StageGuard {
name: &'static str,
start_time: Option<Instant>,
}
impl StageGuard {
pub fn new(name: &'static str) -> Self {
let start_time = if is_profiling_enabled() {
#[cfg(feature = "logging")]
log::trace!("---- enter stage: {name}");
#[cfg(not(feature = "logging"))]
eprintln!("---- enter stage: {}", name);
Some(Instant::now())
} else {
None
};
StageGuard { name, start_time }
}
pub fn elapsed(&self) -> Option<std::time::Duration> {
self.start_time.map(|start| start.elapsed())
}
}
impl Drop for StageGuard {
fn drop(&mut self) {
if let Some(start_time) = self.start_time {
let elapsed = start_time.elapsed();
#[cfg(feature = "logging")]
log::trace!("---- leave stage: {} (took {:?})", self.name, elapsed);
#[cfg(not(feature = "logging"))]
eprintln!("---- leave stage: {} (took {:?})", self.name, elapsed);
}
}
}
#[macro_export]
macro_rules! time_stage {
($name:expr, $block:block) => {{
let _guard = $crate::utils::profiling::StageGuard::new($name);
$block
}};
}
#[macro_export]
macro_rules! with_profiling {
($closure:expr) => {
if $crate::utils::profiling::is_profiling_enabled() {
$closure();
}
};
}
#[macro_export]
macro_rules! with_monitoring {
($closure:expr) => {
if $crate::utils::profiling::is_monitoring_enabled() {
$closure();
}
};
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_stage_guard_creation() {
let _guard = StageGuard::new("TestStage");
}
#[test]
fn test_nested_stages() {
let _outer = StageGuard::new("OuterStage");
{
let _inner = StageGuard::new("InnerStage");
}
}
}