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 mod instrumentation;
75pub mod memory_profiling;
76pub mod opentelemetry_integration;
77pub mod perf_integration;
78pub mod prometheus_metrics;
79pub mod tracing_framework;
80
81pub use entries::{MemoryEntry, TimingEntry};
83pub use memory::{profiling_memory_tracker, MemoryTracker};
84pub use profiler::Profiler;
85pub use timer::Timer;
86
87pub use advanced::{
89 BottleneckConfig, BottleneckDetector, BottleneckReport, BottleneckType, DifferentialProfiler,
90 DifferentialReport, ExportableProfiler, FlameGraphGenerator, FlameGraphNode, MemoryDiff,
91 PerformanceChange, PerformanceStats, ProfileSnapshot, ResourceStats, SystemResourceMonitor,
92 TimingDiff,
93};
94
95pub use comprehensive::{ComprehensiveConfig, ComprehensiveProfiler, ComprehensiveReport};
97
98pub use tracing_framework::{init_tracing, TracingConfig};
100#[cfg(feature = "profiling_advanced")]
101pub use tracing_framework::{PerfZone, SpanGuard, TracingFormat};
102
103#[cfg(feature = "profiling_opentelemetry")]
104pub use opentelemetry_integration::{get_tracer, init_opentelemetry, OtelConfig};
105
106pub use instrumentation::{clear_events, record_event};
107#[cfg(feature = "instrumentation")]
108pub use instrumentation::{
109 get_all_counters, get_counter, get_events, print_counter_summary, record_event_with_duration,
110 InstrumentationEvent, InstrumentationScope, PerformanceCounter,
111};
112pub use perf_integration::PerfCounter;
113pub use perf_integration::PerfEvent;
114#[cfg(all(target_os = "linux", feature = "profiling_perf"))]
115pub use perf_integration::{PerfCounterGroup, PerfMarker};
116pub use prometheus_metrics::MetricsRegistry;
117#[cfg(feature = "profiling_prometheus")]
118pub use prometheus_metrics::{
119 latency_buckets, register_counter, register_counter_vec, register_gauge, register_gauge_vec,
120 register_histogram, register_histogram_vec, size_buckets, PrometheusTimer, SciRS2Metrics,
121};
122
123#[cfg(feature = "profiling_memory")]
124pub use memory_profiling::{disable_profiling, AllocationAnalysis, AllocationTracker, MemoryDelta};
125pub use memory_profiling::{enable_profiling, MemoryProfiler, MemoryStats};
126
127#[macro_export]
129macro_rules! profile_time {
130 ($name:expr, $body:block) => {{
131 let timer = $crate::profiling::Timer::start($name);
132 let result = $body;
133 timer.stop();
134 result
135 }};
136}
137
138#[macro_export]
140macro_rules! profile_memory {
141 ($name:expr, $body:block) => {{
142 let tracker = $crate::profiling::MemoryTracker::start($name);
143 let result = $body;
144 tracker.stop();
145 result
146 }};
147}
148
149#[macro_export]
151macro_rules! profile_time_with_parent {
152 ($name:expr, $parent:expr, $body:block) => {{
153 let timer = $crate::profiling::Timer::start_with_parent($name, $parent);
154 let result = $body;
155 timer.stop();
156 result
157 }};
158}
159
160#[cfg(test)]
161mod tests {
162 use super::*;
163 use std::thread;
164 use std::time::Duration;
165
166 #[test]
167 fn test_timer_basic() {
168 let timer = Timer::start("test_operation");
169 thread::sleep(Duration::from_millis(10));
170 timer.stop();
171
172 let elapsed = timer.elapsed();
173 assert!(elapsed >= Duration::from_millis(10));
174 }
175
176 #[test]
177 fn test_memory_tracker_basic() {
178 let tracker = MemoryTracker::start("test_memory");
179 tracker.stop();
180 }
182
183 #[test]
184 fn test_profiler_integration() {
185 Profiler::global().lock().expect("Operation failed").start();
187
188 let timer = Timer::start("integration_test");
189 thread::sleep(Duration::from_millis(5));
190 timer.stop();
191
192 let stats = Profiler::global()
193 .lock()
194 .expect("Operation failed")
195 .get_timing_stats("integration_test");
196 assert!(stats.is_some());
197
198 let (calls, total, avg, max) = stats.expect("Operation failed");
199 assert_eq!(calls, 1);
200 assert!(total >= Duration::from_millis(5));
201 assert!(avg >= Duration::from_millis(5));
202 assert!(max >= Duration::from_millis(5));
203 }
204
205 #[test]
206 fn test_flame_graph_generator() {
207 let mut generator = advanced::FlameGraphGenerator::new();
208
209 generator.start_call("function_a");
210 generator.start_call("function_b");
211 thread::sleep(Duration::from_millis(1));
212 generator.end_call();
213 generator.end_call();
214
215 let flame_graph = generator.generate();
216 assert!(!flame_graph.children.is_empty());
217 }
218
219 #[test]
220 fn test_bottleneck_detector() {
221 Profiler::global().lock().expect("Operation failed").start();
223
224 let timer = Timer::start("slow_operation");
226 thread::sleep(Duration::from_millis(200));
227 timer.stop();
228
229 let config = advanced::BottleneckConfig {
230 min_execution_threshold: Duration::from_millis(100),
231 min_calls: 1, ..Default::default()
233 };
234
235 let mut detector = advanced::BottleneckDetector::new(config);
236 let reports = detector.analyze(&Profiler::global().lock().expect("Operation failed"));
237
238 assert!(!reports.is_empty());
239 assert_eq!(
240 reports[0].bottleneck_type,
241 advanced::BottleneckType::SlowExecution
242 );
243 }
244
245 #[test]
246 fn test_differential_profiler() {
247 Profiler::global().lock().expect("Operation failed").start();
249
250 let timer = Timer::start("diff_test_operation");
252 thread::sleep(Duration::from_millis(10));
253 timer.stop();
254
255 let mut diff_profiler = advanced::DifferentialProfiler::new();
256 diff_profiler.setbaseline(
257 &Profiler::global().lock().expect("Operation failed"),
258 Some("baseline".to_string()),
259 );
260
261 let timer = Timer::start("diff_test_operation");
263 thread::sleep(Duration::from_millis(20));
264 timer.stop();
265
266 diff_profiler.set_current(
267 &Profiler::global().lock().expect("Operation failed"),
268 Some("current".to_string()),
269 );
270
271 let report = diff_profiler.generate_diff_report();
272 assert!(report.is_some());
273
274 let report = report.expect("Operation failed");
275 assert!(!report.timing_diffs.is_empty() || !report.memory_diffs.is_empty());
276 }
278
279 #[test]
280 fn test_system_resourcemonitor() {
281 let monitor = advanced::SystemResourceMonitor::new(Duration::from_millis(10));
282 monitor.start();
283
284 thread::sleep(Duration::from_millis(50));
285 monitor.stop();
286
287 let stats = monitor.get_stats();
288 assert!(stats.sample_count > 0);
289 }
290
291 #[test]
292 fn test_exportable_profiler() {
293 let mut profiler = advanced::ExportableProfiler::new();
294 profiler.add_metadata("test_run".to_string(), "beta2".to_string());
295
296 profiler.profiler().start();
297
298 let timer = Timer::start("export_test");
299 thread::sleep(Duration::from_millis(5));
300 timer.stop();
301
302 let csv_result = profiler.export_to_csv("/tmp/test_profile.csv");
305 drop(csv_result);
307 }
308}