1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
//! 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
}
}