liboxen 0.53.0

Oxen is a fast data version control system, built with machine learning training data in mind. Designed to handle terabytes of data with ease, using a workflow similar to git. Version both structured and unstructured data of any modality: text, images, video, audio, CSV, Parquet, JSONL, model checkpoints, and more. liboxen is the embeddable core library behind the oxen CLI and server, which power fine tuning and inference pipelines for multimodal LLMs, image models, and video models on Oxen.ai.
//! Performance instrumentation
//!
//! This provides zero-cost performance logging when compiled without the `perf-logging` feature.
//! When the feature is enabled, it provides detailed timing information for instrumented operations.
//!
//! # Usage
//!
//! ```rust
//! use liboxen::perf_guard;
//!
//! fn my_operation() {
//!     let _guard = perf_guard!("my_operation");
//!     // Your code here
//!     // Timing is logged when guard is dropped
//! }
//! ```
//!
//! # Compile-time flags
//!
//! Build with performance logging:
//! ```bash
//! cargo build --features liboxen/perf-logging
//! ```

#[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);

/// Initialize performance logging based on environment variable
///
/// This should be called once at application startup.
/// If `OXEN_PERF_LOGGING` environment variable is set to "1", "true", or "yes",
/// performance logging will be enabled.
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"))]
    {
        // No-op when feature is not enabled
    }
}

/// Check if performance logging is enabled
#[inline]
pub fn is_enabled() -> bool {
    #[cfg(feature = "perf-logging")]
    {
        PERF_LOGGING_ENABLED.load(Ordering::Relaxed)
    }

    #[cfg(not(feature = "perf-logging"))]
    {
        false
    }
}

/// Performance guard that measures execution time
///
/// When dropped, it logs the elapsed time if performance logging is enabled.
/// If the `perf-logging` feature is not enabled at compile time, this becomes
/// a zero-sized type with no runtime overhead.
pub struct PerfGuard {
    #[cfg(feature = "perf-logging")]
    name: &'static str,
    #[cfg(feature = "perf-logging")]
    start: Option<Instant>,
}

impl PerfGuard {
    /// Create a new performance guard
    ///
    /// If performance logging is disabled (either at compile time or runtime),
    /// this returns immediately with minimal overhead.
    #[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) {
        //explicitly calling drop to ensure timing is logged
        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) {
        // No-op - optimizer will eliminate this
    }
}

/// macro to create a performance guard with the current function name
///
/// # Example
///
/// ```rust
/// use liboxen::perf_guard;
///
/// fn my_function() {
///     let _perf = perf_guard!("my_function");
///     // function body
/// }
/// ```
#[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");
        // Guard will be dropped here
    }

    #[test]
    fn test_macro_compiles() {
        let _guard = perf_guard!("test_macro");
        // Should compile and run without errors
    }
}