#[cfg(feature = "perf-logging")]
use std::sync::atomic::{AtomicBool, Ordering};
#[cfg(feature = "perf-logging")]
use std::time::Instant;
#[cfg(feature = "perf-logging")]
static PERF_LOGGING_ENABLED: AtomicBool = AtomicBool::new(false);
pub fn init_perf_logging() {
#[cfg(feature = "perf-logging")]
{
let enabled = std::env::var("OXEN_PERF_LOGGING")
.map(|v| v == "1" || v.eq_ignore_ascii_case("true") || v.eq_ignore_ascii_case("yes"))
.unwrap_or(false);
PERF_LOGGING_ENABLED.store(enabled, Ordering::Relaxed);
if enabled {
log::info!("Performance logging enabled");
}
}
#[cfg(not(feature = "perf-logging"))]
{
}
}
#[inline]
pub fn is_enabled() -> bool {
#[cfg(feature = "perf-logging")]
{
PERF_LOGGING_ENABLED.load(Ordering::Relaxed)
}
#[cfg(not(feature = "perf-logging"))]
{
false
}
}
pub struct PerfGuard {
#[cfg(feature = "perf-logging")]
name: &'static str,
#[cfg(feature = "perf-logging")]
start: Option<Instant>,
}
impl PerfGuard {
#[cfg(feature = "perf-logging")]
pub fn new(name: &'static str) -> Self {
if is_enabled() {
Self {
name,
start: Some(Instant::now()),
}
} else {
Self { name, start: None }
}
}
#[cfg(not(feature = "perf-logging"))]
pub fn new(_name: &'static str) -> Self {
Self {}
}
}
#[cfg(feature = "perf-logging")]
impl Drop for PerfGuard {
fn drop(&mut self) {
if let Some(start) = self.start {
let elapsed = start.elapsed();
log::info!("[PERF] {} took {:?}", self.name, elapsed);
}
}
}
#[cfg(not(feature = "perf-logging"))]
impl Drop for PerfGuard {
#[inline]
fn drop(&mut self) {
}
}
#[macro_export]
macro_rules! perf_guard {
($name:expr) => {
$crate::util::perf::PerfGuard::new($name)
};
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_perf_guard_compiles() {
let _guard = PerfGuard::new("test_operation");
}
#[test]
fn test_macro_compiles() {
let _guard = perf_guard!("test_macro");
}
}