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