scirs2_core/profiling/
mod.rs1pub mod advanced;
56pub mod comprehensive;
57pub mod entries;
58pub mod memory;
59pub mod profiler;
60pub mod timer;
61
62pub mod adaptive;
64pub mod continuousmonitoring;
65pub mod coverage;
66pub mod dashboards;
67pub mod flame_graph_svg;
68pub mod hardware_counters;
69pub mod performance_hints;
70pub mod production;
71pub mod system_monitor;
72
73pub use entries::{MemoryEntry, TimingEntry};
75pub use memory::{profiling_memory_tracker, MemoryTracker};
76pub use profiler::Profiler;
77pub use timer::Timer;
78
79pub use advanced::{
81 BottleneckConfig, BottleneckDetector, BottleneckReport, BottleneckType, DifferentialProfiler,
82 DifferentialReport, ExportableProfiler, FlameGraphGenerator, FlameGraphNode, MemoryDiff,
83 PerformanceChange, PerformanceStats, ProfileSnapshot, ResourceStats, SystemResourceMonitor,
84 TimingDiff,
85};
86
87pub use comprehensive::{ComprehensiveConfig, ComprehensiveProfiler, ComprehensiveReport};
89
90#[macro_export]
92macro_rules! profile_time {
93 ($name:expr, $body:block) => {{
94 let timer = $crate::profiling::Timer::start($name);
95 let result = $body;
96 timer.stop();
97 result
98 }};
99}
100
101#[macro_export]
103macro_rules! profile_memory {
104 ($name:expr, $body:block) => {{
105 let tracker = $crate::profiling::MemoryTracker::start($name);
106 let result = $body;
107 tracker.stop();
108 result
109 }};
110}
111
112#[macro_export]
114macro_rules! profile_time_with_parent {
115 ($name:expr, $parent:expr, $body:block) => {{
116 let timer = $crate::profiling::Timer::start_with_parent($name, $parent);
117 let result = $body;
118 timer.stop();
119 result
120 }};
121}
122
123#[cfg(test)]
124mod tests {
125 use super::*;
126 use std::thread;
127 use std::time::Duration;
128
129 #[test]
130 fn test_timer_basic() {
131 let timer = Timer::start("test_operation");
132 thread::sleep(Duration::from_millis(10));
133 timer.stop();
134
135 let elapsed = timer.elapsed();
136 assert!(elapsed >= Duration::from_millis(10));
137 }
138
139 #[test]
140 fn test_memory_tracker_basic() {
141 let tracker = MemoryTracker::start("test_memory");
142 tracker.stop();
143 }
145
146 #[test]
147 fn test_profiler_integration() {
148 Profiler::global().lock().expect("Operation failed").start();
150
151 let timer = Timer::start("integration_test");
152 thread::sleep(Duration::from_millis(5));
153 timer.stop();
154
155 let stats = Profiler::global()
156 .lock()
157 .expect("Operation failed")
158 .get_timing_stats("integration_test");
159 assert!(stats.is_some());
160
161 let (calls, total, avg, max) = stats.expect("Operation failed");
162 assert_eq!(calls, 1);
163 assert!(total >= Duration::from_millis(5));
164 assert!(avg >= Duration::from_millis(5));
165 assert!(max >= Duration::from_millis(5));
166 }
167
168 #[test]
169 fn test_flame_graph_generator() {
170 let mut generator = advanced::FlameGraphGenerator::new();
171
172 generator.start_call("function_a");
173 generator.start_call("function_b");
174 thread::sleep(Duration::from_millis(1));
175 generator.end_call();
176 generator.end_call();
177
178 let flame_graph = generator.generate();
179 assert!(!flame_graph.children.is_empty());
180 }
181
182 #[test]
183 fn test_bottleneck_detector() {
184 Profiler::global().lock().expect("Operation failed").start();
186
187 let timer = Timer::start("slow_operation");
189 thread::sleep(Duration::from_millis(200));
190 timer.stop();
191
192 let config = advanced::BottleneckConfig {
193 min_execution_threshold: Duration::from_millis(100),
194 min_calls: 1, ..Default::default()
196 };
197
198 let mut detector = advanced::BottleneckDetector::new(config);
199 let reports = detector.analyze(&Profiler::global().lock().expect("Operation failed"));
200
201 assert!(!reports.is_empty());
202 assert_eq!(
203 reports[0].bottleneck_type,
204 advanced::BottleneckType::SlowExecution
205 );
206 }
207
208 #[test]
209 fn test_differential_profiler() {
210 Profiler::global().lock().expect("Operation failed").start();
212
213 let timer = Timer::start("diff_test_operation");
215 thread::sleep(Duration::from_millis(10));
216 timer.stop();
217
218 let mut diff_profiler = advanced::DifferentialProfiler::new();
219 diff_profiler.setbaseline(
220 &Profiler::global().lock().expect("Operation failed"),
221 Some("baseline".to_string()),
222 );
223
224 let timer = Timer::start("diff_test_operation");
226 thread::sleep(Duration::from_millis(20));
227 timer.stop();
228
229 diff_profiler.set_current(
230 &Profiler::global().lock().expect("Operation failed"),
231 Some("current".to_string()),
232 );
233
234 let report = diff_profiler.generate_diff_report();
235 assert!(report.is_some());
236
237 let report = report.expect("Operation failed");
238 assert!(!report.timing_diffs.is_empty() || !report.memory_diffs.is_empty());
239 }
241
242 #[test]
243 fn test_system_resourcemonitor() {
244 let monitor = advanced::SystemResourceMonitor::new(Duration::from_millis(10));
245 monitor.start();
246
247 thread::sleep(Duration::from_millis(50));
248 monitor.stop();
249
250 let stats = monitor.get_stats();
251 assert!(stats.sample_count > 0);
252 }
253
254 #[test]
255 fn test_exportable_profiler() {
256 let mut profiler = advanced::ExportableProfiler::new();
257 profiler.add_metadata("test_run".to_string(), "beta2".to_string());
258
259 profiler.profiler().start();
260
261 let timer = Timer::start("export_test");
262 thread::sleep(Duration::from_millis(5));
263 timer.stop();
264
265 let csv_result = profiler.export_to_csv("/tmp/test_profile.csv");
268 drop(csv_result);
270 }
271}