scirs2-core 0.4.2

Core utilities and common functionality for SciRS2 (scirs2-core)
Documentation
//! Memory allocation tracking functionality for profiling

use crate::profiling::profiler::Profiler;

/// Memory allocation tracker
pub struct MemoryTracker {
    /// Name of the operation being tracked
    name: String,
    /// Start memory usage
    start_memory: usize,
    /// Whether the tracker is currently running
    running: bool,
    /// Whether to automatically report when dropped
    auto_report: bool,
}

impl MemoryTracker {
    /// Start a new memory tracker with the given name
    pub fn start(name: &str) -> Self {
        let current_memory = Self::current_memory_usage();
        let tracker = Self {
            name: name.to_string(),
            start_memory: current_memory,
            running: true,
            auto_report: true,
        };
        if let Ok(mut profiler) = Profiler::global().lock() {
            profiler.register_memory_tracker_start(&tracker);
        }
        tracker
    }

    /// Stop the tracker and record the memory usage
    pub fn stop(&self) {
        if !self.running {
            return;
        }

        let current_memory = Self::current_memory_usage();
        let memory_delta = current_memory.saturating_sub(self.start_memory);
        if let Ok(mut profiler) = Profiler::global().lock() {
            profiler.register_memory_tracker_stop(&self.name, memory_delta);
        }
    }

    /// Track memory usage for a function call and return its result
    pub fn track_function<F, R>(name: &str, f: F) -> R
    where
        F: FnOnce() -> R,
    {
        let tracker = Self::start(name);
        let result = f();
        tracker.stop();
        result
    }

    /// Get the current memory delta without stopping the tracker
    pub fn memory_delta(&self) -> isize {
        let current_memory = Self::current_memory_usage();
        current_memory as isize - self.start_memory as isize
    }

    /// Disable auto-reporting when dropped
    pub fn without_auto_report(mut self) -> Self {
        self.auto_report = false;
        self
    }

    /// Get the name of the tracker
    pub fn name(&self) -> &str {
        &self.name
    }

    /// Get the start memory usage
    pub fn start_memory(&self) -> usize {
        self.start_memory
    }

    /// Check if the tracker is running
    pub fn is_running(&self) -> bool {
        self.running
    }

    /// Get the current memory usage (platform-dependent implementation)
    fn current_memory_usage() -> usize {
        // This is a simplified implementation that doesn't actually track real memory
        // A real implementation would use platform-specific APIs to get memory usage
        #[cfg(target_os = "linux")]
        {
            // On Linux, we would read /proc/self/statm
            0
        }

        #[cfg(target_os = "macos")]
        {
            // On macOS, we would use task_info
            0
        }

        #[cfg(target_os = "windows")]
        {
            // On Windows, we would use GetProcessMemoryInfo
            0
        }

        #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
        {
            // Fallback for other platforms
            0
        }
    }
}

impl Drop for MemoryTracker {
    fn drop(&mut self) {
        if self.running && self.auto_report {
            let current_memory = Self::current_memory_usage();
            let memory_delta = current_memory.saturating_sub(self.start_memory);
            if let Ok(mut profiler) = Profiler::global().lock() {
                profiler.register_memory_tracker_stop(&self.name, memory_delta);
            }
        }
    }
}

/// Access a memory tracker from the profiling module to avoid name conflicts
#[allow(dead_code)]
pub fn profiling_memory_tracker() -> &'static MemoryTracker {
    // Create a dummy memory tracker for static access
    static MEMORY_TRACKER: once_cell::sync::Lazy<MemoryTracker> =
        once_cell::sync::Lazy::new(|| MemoryTracker {
            name: "global".to_string(),
            start_memory: 0,
            running: false,
            auto_report: false,
        });
    &MEMORY_TRACKER
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_memory_tracker_basic() {
        let tracker = MemoryTracker::start("test_memory");
        tracker.stop();
        // Memory tracking is a placeholder, so we just test that it doesn't panic
    }
}