Skip to main content

trustformers_debug/performance/
optimization.rs

1//! Performance optimization system for production debugging
2//!
3//! This module provides advanced performance optimizations including low overhead
4//! sessions, lazy evaluation, incremental processing, background processing,
5//! and selective debugging capabilities for production environments.
6// reason: debug/profiling scaffolding — structs are constructed and their fields/methods
7// are retained for the data model, serialization completeness, and future consumers that
8// do not yet read every member. Consolidated from many item-level #[allow(dead_code)].
9#![allow(dead_code)]
10
11use crate::core::session::{DebugConfig, DebugSession};
12use anyhow::Result;
13use serde::{Deserialize, Serialize};
14use std::collections::HashMap;
15
16/// Performance configuration for optimized debugging
17#[derive(Debug, Clone, Serialize, Deserialize)]
18pub struct PerformanceConfig {
19    /// Enable low overhead mode
20    pub low_overhead_mode: bool,
21    /// Enable selective debugging
22    pub selective_debugging: bool,
23    /// Enable lazy evaluation
24    pub lazy_evaluation: bool,
25    /// Enable incremental updates
26    pub incremental_updates: bool,
27    /// Enable background processing
28    pub background_processing: bool,
29    /// Sampling rate for performance-critical operations
30    pub sampling_rate: f32,
31    /// Maximum memory usage for debugging (in MB)
32    pub max_memory_mb: usize,
33    /// Maximum CPU usage percentage for debugging
34    pub max_cpu_percentage: f32,
35    /// Batch size for background processing
36    pub background_batch_size: usize,
37    /// Update interval for incremental processing (in milliseconds)
38    pub incremental_update_interval_ms: u64,
39}
40
41impl Default for PerformanceConfig {
42    fn default() -> Self {
43        Self {
44            low_overhead_mode: false,
45            selective_debugging: false,
46            lazy_evaluation: true,
47            incremental_updates: true,
48            background_processing: true,
49            sampling_rate: 1.0,
50            max_memory_mb: 1024,      // 1GB
51            max_cpu_percentage: 25.0, // 25% CPU
52            background_batch_size: 100,
53            incremental_update_interval_ms: 100,
54        }
55    }
56}
57
58/// Low overhead debugging session optimized for production use
59pub struct LowOverheadDebugSession {
60    session: DebugSession,
61    performance_config: PerformanceConfig,
62    selective_components: Vec<DebugComponent>,
63    lazy_evaluator: LazyEvaluator,
64    incremental_processor: IncrementalProcessor,
65    background_processor: Option<BackgroundProcessor>,
66}
67
68/// Debug component types for selective debugging
69#[derive(Debug, Clone, PartialEq, Eq, Hash)]
70pub enum DebugComponent {
71    TensorInspection,
72    GradientDebugging,
73    ModelDiagnostics,
74    MemoryProfiling,
75    ComputationGraphAnalysis,
76    AnomalyDetection,
77    PerformanceProfiling,
78    ArchitectureAnalysis,
79    BehaviorAnalysis,
80    TrainingDynamics,
81}
82
83impl LowOverheadDebugSession {
84    /// Create a new low overhead debug session
85    pub fn new(
86        mut config: DebugConfig,
87        performance_config: PerformanceConfig,
88        selective_components: Vec<DebugComponent>,
89    ) -> Self {
90        // Apply low overhead optimizations to config
91        if performance_config.low_overhead_mode {
92            config = Self::apply_low_overhead_config(config, &performance_config);
93        }
94
95        let session = DebugSession::new(config);
96        let lazy_evaluator = LazyEvaluator::new();
97        let incremental_processor =
98            IncrementalProcessor::new(performance_config.incremental_update_interval_ms);
99
100        let background_processor = if performance_config.background_processing {
101            Some(BackgroundProcessor::new(
102                performance_config.background_batch_size,
103            ))
104        } else {
105            None
106        };
107
108        Self {
109            session,
110            performance_config,
111            selective_components,
112            lazy_evaluator,
113            incremental_processor,
114            background_processor,
115        }
116    }
117
118    /// Apply low overhead configuration
119    fn apply_low_overhead_config(
120        mut config: DebugConfig,
121        perf_config: &PerformanceConfig,
122    ) -> DebugConfig {
123        config.sampling_rate = perf_config.sampling_rate;
124        config.max_tracked_tensors = std::cmp::min(config.max_tracked_tensors, 100);
125        config.max_gradient_history = std::cmp::min(config.max_gradient_history, 20);
126
127        // Disable expensive features in low overhead mode
128        if perf_config.low_overhead_mode {
129            config.enable_visualization = false;
130            config.enable_memory_profiling = false;
131        }
132
133        config
134    }
135
136    /// Start optimized debugging session
137    pub async fn start(&mut self) -> Result<()> {
138        // Start selective components only
139        for component in &self.selective_components {
140            match component {
141                DebugComponent::TensorInspection
142                    if self.session.config().enable_tensor_inspection =>
143                {
144                    self.session.tensor_inspector_mut().start().await?;
145                },
146                DebugComponent::GradientDebugging
147                    if self.session.config().enable_gradient_debugging =>
148                {
149                    self.session.gradient_debugger_mut().start().await?;
150                },
151                DebugComponent::ModelDiagnostics
152                    if self.session.config().enable_model_diagnostics =>
153                {
154                    self.session.model_diagnostics_mut().start().await?;
155                },
156                DebugComponent::MemoryProfiling => {
157                    if let Some(profiler) = self.session.memory_profiler_mut() {
158                        profiler.start().await?;
159                    }
160                },
161                DebugComponent::AnomalyDetection => {
162                    self.session.anomaly_detector_mut().start().await?;
163                },
164                DebugComponent::PerformanceProfiling => {
165                    self.session.profiler_mut().start().await?;
166                },
167                _ => {
168                    // Other components started on-demand
169                },
170            }
171        }
172
173        // Start background processor if enabled
174        if let Some(ref mut bg_processor) = self.background_processor {
175            bg_processor.start().await?;
176        }
177
178        Ok(())
179    }
180
181    /// Add data for lazy evaluation
182    pub fn add_lazy_evaluation<T: 'static + Send + Sync>(
183        &mut self,
184        key: String,
185        computation: Box<dyn LazyComputation<T>>,
186    ) {
187        self.lazy_evaluator.add_computation(key, computation);
188    }
189
190    /// Process incremental update
191    pub async fn process_incremental_update(&mut self, data: IncrementalData) -> Result<()> {
192        self.incremental_processor.process_update(data).await
193    }
194
195    /// Submit data for background processing
196    pub async fn submit_background_task(&mut self, task: BackgroundTask) -> Result<()> {
197        if let Some(ref mut bg_processor) = self.background_processor {
198            bg_processor.submit_task(task).await
199        } else {
200            Err(anyhow::anyhow!("Background processing not enabled"))
201        }
202    }
203
204    /// Get performance metrics
205    pub fn get_performance_metrics(&self) -> PerformanceMetrics {
206        PerformanceMetrics {
207            memory_usage_mb: self.get_memory_usage_mb(),
208            cpu_usage_percentage: self.get_cpu_usage_percentage(),
209            lazy_computations_pending: self.lazy_evaluator.pending_count(),
210            incremental_updates_processed: self.incremental_processor.processed_count(),
211            background_tasks_queued: self
212                .background_processor
213                .as_ref()
214                .map(|p| p.queued_count())
215                .unwrap_or(0),
216        }
217    }
218
219    /// Check if performance limits are exceeded
220    pub fn is_within_performance_limits(&self) -> bool {
221        let metrics = self.get_performance_metrics();
222        metrics.memory_usage_mb <= self.performance_config.max_memory_mb
223            && metrics.cpu_usage_percentage <= self.performance_config.max_cpu_percentage
224    }
225
226    /// Get current memory usage in MB
227    fn get_memory_usage_mb(&self) -> usize {
228        // Simplified implementation - would use actual memory monitoring
229        0
230    }
231
232    /// Get current CPU usage percentage
233    fn get_cpu_usage_percentage(&self) -> f32 {
234        // Simplified implementation - would use actual CPU monitoring
235        0.0
236    }
237}
238
239/// Lazy evaluation system for expensive computations
240pub struct LazyEvaluator {
241    computations: HashMap<String, Box<dyn std::any::Any + Send + Sync>>,
242    evaluated: HashMap<String, bool>,
243}
244
245impl Default for LazyEvaluator {
246    fn default() -> Self {
247        Self::new()
248    }
249}
250
251impl LazyEvaluator {
252    pub fn new() -> Self {
253        Self {
254            computations: HashMap::new(),
255            evaluated: HashMap::new(),
256        }
257    }
258
259    /// Add a lazy computation
260    pub fn add_computation<T: 'static + Send + Sync>(
261        &mut self,
262        key: String,
263        computation: Box<dyn LazyComputation<T>>,
264    ) {
265        self.computations.insert(key.clone(), Box::new(computation));
266        self.evaluated.insert(key, false);
267    }
268
269    /// Evaluate computation on demand
270    pub async fn evaluate<T: 'static>(&mut self, key: &str) -> Result<Option<T>> {
271        if let Some(computation) = self.computations.remove(key) {
272            if let Ok(lazy_comp) = computation.downcast::<Box<dyn LazyComputation<T>>>() {
273                let result = lazy_comp.compute().await?;
274                self.evaluated.insert(key.to_string(), true);
275                return Ok(Some(result));
276            }
277        }
278        Ok(None)
279    }
280
281    /// Get number of pending computations
282    pub fn pending_count(&self) -> usize {
283        self.evaluated.values().filter(|&&v| !v).count()
284    }
285
286    /// Clear all computations
287    pub fn clear(&mut self) {
288        self.computations.clear();
289        self.evaluated.clear();
290    }
291}
292
293/// Trait for lazy computations
294pub trait LazyComputation<T>: Send + Sync {
295    fn compute(
296        &self,
297    ) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<T>> + Send + '_>>;
298}
299
300/// Incremental processing system for efficient updates
301pub struct IncrementalProcessor {
302    update_interval_ms: u64,
303    last_update: std::time::Instant,
304    accumulated_data: Vec<IncrementalData>,
305    processed_count: usize,
306}
307
308impl IncrementalProcessor {
309    pub fn new(update_interval_ms: u64) -> Self {
310        Self {
311            update_interval_ms,
312            last_update: std::time::Instant::now(),
313            accumulated_data: Vec::new(),
314            processed_count: 0,
315        }
316    }
317
318    /// Process incremental update
319    pub async fn process_update(&mut self, data: IncrementalData) -> Result<()> {
320        self.accumulated_data.push(data);
321
322        // Check if it's time to process accumulated data
323        if self.last_update.elapsed().as_millis() >= self.update_interval_ms as u128 {
324            self.process_accumulated_data().await?;
325            self.last_update = std::time::Instant::now();
326        }
327
328        Ok(())
329    }
330
331    /// Force processing of accumulated data
332    pub async fn flush(&mut self) -> Result<()> {
333        self.process_accumulated_data().await?;
334        self.last_update = std::time::Instant::now();
335        Ok(())
336    }
337
338    /// Process all accumulated data
339    async fn process_accumulated_data(&mut self) -> Result<()> {
340        if !self.accumulated_data.is_empty() {
341            // Process the accumulated data in batch
342            let batch_size = self.accumulated_data.len();
343
344            // Simplified processing - would implement actual incremental analysis
345            for _data in self.accumulated_data.drain(..) {
346                self.processed_count += 1;
347            }
348
349            tracing::debug!("Processed {} incremental updates", batch_size);
350        }
351
352        Ok(())
353    }
354
355    /// Get number of processed updates
356    pub fn processed_count(&self) -> usize {
357        self.processed_count
358    }
359}
360
361/// Data for incremental processing
362#[derive(Debug, Clone)]
363pub enum IncrementalData {
364    TensorUpdate {
365        tensor_id: String,
366        values: Vec<f32>,
367    },
368    GradientUpdate {
369        layer_id: String,
370        gradients: Vec<f32>,
371    },
372    MetricUpdate {
373        metric_name: String,
374        value: f64,
375        timestamp: std::time::Instant,
376    },
377    PerformanceUpdate {
378        operation: String,
379        latency_ms: f64,
380    },
381}
382
383/// Background processing system for non-critical tasks
384pub struct BackgroundProcessor {
385    batch_size: usize,
386    task_queue: Vec<BackgroundTask>,
387    processed_count: usize,
388    worker_handle: Option<tokio::task::JoinHandle<()>>,
389}
390
391impl BackgroundProcessor {
392    pub fn new(batch_size: usize) -> Self {
393        Self {
394            batch_size,
395            task_queue: Vec::new(),
396            processed_count: 0,
397            worker_handle: None,
398        }
399    }
400
401    /// Start background processing
402    pub async fn start(&mut self) -> Result<()> {
403        let (_sender, mut receiver) = tokio::sync::mpsc::channel::<BackgroundTask>(1000);
404
405        // Spawn background worker
406        let batch_size = self.batch_size;
407        let handle = tokio::spawn(async move {
408            let mut batch = Vec::with_capacity(batch_size);
409
410            while let Some(task) = receiver.recv().await {
411                batch.push(task);
412
413                if batch.len() >= batch_size {
414                    Self::process_batch(&mut batch).await;
415                    batch.clear();
416                }
417            }
418
419            // Process remaining tasks
420            if !batch.is_empty() {
421                Self::process_batch(&mut batch).await;
422            }
423        });
424
425        self.worker_handle = Some(handle);
426        Ok(())
427    }
428
429    /// Submit task for background processing
430    pub async fn submit_task(&mut self, task: BackgroundTask) -> Result<()> {
431        self.task_queue.push(task);
432        Ok(())
433    }
434
435    /// Process a batch of background tasks
436    async fn process_batch(batch: &mut Vec<BackgroundTask>) {
437        for task in batch.drain(..) {
438            match task {
439                BackgroundTask::ComputeStatistics { data } => {
440                    // Compute statistics in background
441                    let _stats = Self::compute_statistics(&data).await;
442                },
443                BackgroundTask::GenerateVisualization { plot_data } => {
444                    // Generate visualization in background
445                    let _viz = Self::generate_visualization(&plot_data).await;
446                },
447                BackgroundTask::ExportData { data, format } => {
448                    // Export data in background
449                    let _result = Self::export_data(&data, &format).await;
450                },
451                BackgroundTask::CleanupResources { resource_ids } => {
452                    // Cleanup resources in background
453                    Self::cleanup_resources(&resource_ids).await;
454                },
455            }
456        }
457    }
458
459    /// Compute statistics for background task
460    async fn compute_statistics(data: &[f32]) -> Vec<f64> {
461        // Simplified implementation
462        tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
463        vec![data.iter().map(|&x| x as f64).sum()]
464    }
465
466    /// Generate visualization for background task
467    async fn generate_visualization(plot_data: &PlotData) -> String {
468        // Simplified implementation
469        tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;
470        format!(
471            "Generated visualization for {} data points",
472            plot_data.points.len()
473        )
474    }
475
476    /// Export data for background task
477    async fn export_data(data: &ExportData, format: &str) -> Result<String> {
478        // Simplified implementation
479        tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
480        Ok(format!(
481            "Exported {} items in {} format",
482            data.items.len(),
483            format
484        ))
485    }
486
487    /// Cleanup resources for background task
488    async fn cleanup_resources(resource_ids: &[String]) {
489        // Simplified implementation
490        tokio::time::sleep(tokio::time::Duration::from_millis(20)).await;
491        tracing::debug!("Cleaned up {} resources", resource_ids.len());
492    }
493
494    /// Get number of queued tasks
495    pub fn queued_count(&self) -> usize {
496        self.task_queue.len()
497    }
498
499    /// Stop background processing
500    pub async fn stop(&mut self) -> Result<()> {
501        if let Some(handle) = self.worker_handle.take() {
502            handle.abort();
503        }
504        Ok(())
505    }
506}
507
508/// Background task types
509#[derive(Debug, Clone)]
510pub enum BackgroundTask {
511    ComputeStatistics { data: Vec<f32> },
512    GenerateVisualization { plot_data: PlotData },
513    ExportData { data: ExportData, format: String },
514    CleanupResources { resource_ids: Vec<String> },
515}
516
517/// Plot data for background visualization
518#[derive(Debug, Clone)]
519pub struct PlotData {
520    pub points: Vec<(f64, f64)>,
521    pub title: String,
522    pub x_label: String,
523    pub y_label: String,
524}
525
526/// Export data for background processing
527#[derive(Debug, Clone)]
528pub struct ExportData {
529    pub items: Vec<String>,
530    pub metadata: HashMap<String, String>,
531}
532
533/// Performance metrics for monitoring
534#[derive(Debug, Serialize, Deserialize)]
535pub struct PerformanceMetrics {
536    pub memory_usage_mb: usize,
537    pub cpu_usage_percentage: f32,
538    pub lazy_computations_pending: usize,
539    pub incremental_updates_processed: usize,
540    pub background_tasks_queued: usize,
541}
542
543/// Selective debugging configuration
544#[derive(Debug, Clone)]
545pub struct SelectiveDebugConfig {
546    pub components: Vec<DebugComponent>,
547    pub sampling_rules: HashMap<DebugComponent, f32>,
548    pub priority_rules: HashMap<DebugComponent, DebugPriority>,
549    pub resource_limits: ResourceLimits,
550}
551
552/// Debug priority levels
553#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
554pub enum DebugPriority {
555    Low,
556    Medium,
557    High,
558    Critical,
559}
560
561/// Resource limits for selective debugging
562#[derive(Debug, Clone)]
563pub struct ResourceLimits {
564    pub max_memory_per_component_mb: usize,
565    pub max_cpu_per_component_percentage: f32,
566    pub max_concurrent_operations: usize,
567}
568
569impl SelectiveDebugConfig {
570    /// Create config for production monitoring
571    pub fn production_monitoring() -> Self {
572        let mut sampling_rules = HashMap::new();
573        sampling_rules.insert(DebugComponent::AnomalyDetection, 1.0);
574        sampling_rules.insert(DebugComponent::PerformanceProfiling, 0.1);
575        sampling_rules.insert(DebugComponent::MemoryProfiling, 0.05);
576
577        let mut priority_rules = HashMap::new();
578        priority_rules.insert(DebugComponent::AnomalyDetection, DebugPriority::Critical);
579        priority_rules.insert(DebugComponent::PerformanceProfiling, DebugPriority::Medium);
580
581        Self {
582            components: vec![
583                DebugComponent::AnomalyDetection,
584                DebugComponent::PerformanceProfiling,
585            ],
586            sampling_rules,
587            priority_rules,
588            resource_limits: ResourceLimits {
589                max_memory_per_component_mb: 50,
590                max_cpu_per_component_percentage: 5.0,
591                max_concurrent_operations: 2,
592            },
593        }
594    }
595
596    /// Create config for development debugging
597    pub fn development_debugging() -> Self {
598        let mut sampling_rules = HashMap::new();
599        sampling_rules.insert(DebugComponent::TensorInspection, 0.5);
600        sampling_rules.insert(DebugComponent::GradientDebugging, 1.0);
601        sampling_rules.insert(DebugComponent::ModelDiagnostics, 1.0);
602        sampling_rules.insert(DebugComponent::AnomalyDetection, 1.0);
603
604        let mut priority_rules = HashMap::new();
605        priority_rules.insert(DebugComponent::GradientDebugging, DebugPriority::High);
606        priority_rules.insert(DebugComponent::AnomalyDetection, DebugPriority::Critical);
607        priority_rules.insert(DebugComponent::ModelDiagnostics, DebugPriority::Medium);
608
609        Self {
610            components: vec![
611                DebugComponent::TensorInspection,
612                DebugComponent::GradientDebugging,
613                DebugComponent::ModelDiagnostics,
614                DebugComponent::AnomalyDetection,
615            ],
616            sampling_rules,
617            priority_rules,
618            resource_limits: ResourceLimits {
619                max_memory_per_component_mb: 200,
620                max_cpu_per_component_percentage: 15.0,
621                max_concurrent_operations: 6,
622            },
623        }
624    }
625}
626
627/// Create optimized debug session for production use
628pub fn optimized_debug_session(
629    selective_config: SelectiveDebugConfig,
630    performance_config: PerformanceConfig,
631) -> LowOverheadDebugSession {
632    let debug_config = DebugConfig {
633        enable_tensor_inspection: selective_config
634            .components
635            .contains(&DebugComponent::TensorInspection),
636        enable_gradient_debugging: selective_config
637            .components
638            .contains(&DebugComponent::GradientDebugging),
639        enable_model_diagnostics: selective_config
640            .components
641            .contains(&DebugComponent::ModelDiagnostics),
642        enable_memory_profiling: selective_config
643            .components
644            .contains(&DebugComponent::MemoryProfiling),
645        enable_computation_graph_analysis: selective_config
646            .components
647            .contains(&DebugComponent::ComputationGraphAnalysis),
648        sampling_rate: performance_config.sampling_rate,
649        max_tracked_tensors: if performance_config.low_overhead_mode { 50 } else { 500 },
650        max_gradient_history: if performance_config.low_overhead_mode { 10 } else { 50 },
651        ..Default::default()
652    };
653
654    LowOverheadDebugSession::new(
655        debug_config,
656        performance_config,
657        selective_config.components,
658    )
659}
660
661/// Create ultra-low overhead session for production monitoring
662pub fn ultra_low_overhead_session() -> LowOverheadDebugSession {
663    let selective_config = SelectiveDebugConfig::production_monitoring();
664    let performance_config = PerformanceConfig {
665        low_overhead_mode: true,
666        selective_debugging: true,
667        lazy_evaluation: true,
668        incremental_updates: true,
669        background_processing: true,
670        sampling_rate: 0.01,
671        max_memory_mb: 100,
672        max_cpu_percentage: 5.0,
673        background_batch_size: 50,
674        incremental_update_interval_ms: 1000,
675    };
676
677    optimized_debug_session(selective_config, performance_config)
678}
679
680// ─────────────────────────────────────────────────────────────────────────────
681// Tests
682// ─────────────────────────────────────────────────────────────────────────────
683
684#[cfg(test)]
685mod tests {
686    use super::*;
687
688    // ── PerformanceConfig::default() ────────────────────────────────────────
689
690    #[test]
691    fn test_performance_config_default() {
692        let cfg = PerformanceConfig::default();
693        assert!(!cfg.low_overhead_mode);
694        assert!(!cfg.selective_debugging);
695        assert!(cfg.lazy_evaluation);
696        assert!(cfg.incremental_updates);
697        assert!(cfg.background_processing);
698        assert!((cfg.sampling_rate - 1.0).abs() < 1e-6);
699        assert!(cfg.max_memory_mb > 0);
700        assert!(cfg.max_cpu_percentage > 0.0);
701        assert!(cfg.background_batch_size > 0);
702        assert!(cfg.incremental_update_interval_ms > 0);
703    }
704
705    #[test]
706    fn test_performance_config_low_overhead() {
707        let cfg = PerformanceConfig {
708            low_overhead_mode: true,
709            selective_debugging: true,
710            sampling_rate: 0.01,
711            max_memory_mb: 100,
712            max_cpu_percentage: 5.0,
713            ..PerformanceConfig::default()
714        };
715        assert!(cfg.low_overhead_mode);
716        assert!((cfg.sampling_rate - 0.01).abs() < 1e-6);
717    }
718
719    // ── DebugComponent variants ───────────────────────────────────────────
720
721    #[test]
722    fn test_debug_component_variants() {
723        let components = [
724            DebugComponent::TensorInspection,
725            DebugComponent::GradientDebugging,
726            DebugComponent::ModelDiagnostics,
727            DebugComponent::MemoryProfiling,
728            DebugComponent::ComputationGraphAnalysis,
729            DebugComponent::AnomalyDetection,
730            DebugComponent::PerformanceProfiling,
731            DebugComponent::ArchitectureAnalysis,
732            DebugComponent::BehaviorAnalysis,
733            DebugComponent::TrainingDynamics,
734        ];
735        for c in &components {
736            assert!(!format!("{:?}", c).is_empty());
737        }
738    }
739
740    #[test]
741    fn test_debug_component_equality() {
742        assert_eq!(
743            DebugComponent::TensorInspection,
744            DebugComponent::TensorInspection
745        );
746        assert_ne!(
747            DebugComponent::TensorInspection,
748            DebugComponent::GradientDebugging
749        );
750    }
751
752    // ── DebugPriority variants ────────────────────────────────────────────
753
754    #[test]
755    fn test_debug_priority_variants() {
756        let priorities = [
757            DebugPriority::Low,
758            DebugPriority::Medium,
759            DebugPriority::High,
760            DebugPriority::Critical,
761        ];
762        for p in &priorities {
763            assert!(!format!("{:?}", p).is_empty());
764        }
765    }
766
767    // ── SelectiveDebugConfig ──────────────────────────────────────────────
768
769    #[test]
770    fn test_production_monitoring_config() {
771        let cfg = SelectiveDebugConfig::production_monitoring();
772        assert!(cfg.components.contains(&DebugComponent::AnomalyDetection));
773        assert!(!cfg.sampling_rules.is_empty());
774        assert!(!cfg.priority_rules.is_empty());
775    }
776
777    #[test]
778    fn test_development_debugging_config() {
779        let cfg = SelectiveDebugConfig::development_debugging();
780        assert!(cfg.components.contains(&DebugComponent::GradientDebugging));
781        assert!(cfg.components.contains(&DebugComponent::ModelDiagnostics));
782        assert!(cfg.resource_limits.max_memory_per_component_mb > 0);
783    }
784
785    #[test]
786    fn test_resource_limits_in_production_config() {
787        let cfg = SelectiveDebugConfig::production_monitoring();
788        let limits = &cfg.resource_limits;
789        assert!(limits.max_memory_per_component_mb > 0);
790        assert!(limits.max_cpu_per_component_percentage > 0.0);
791        assert!(limits.max_concurrent_operations > 0);
792    }
793
794    // ── optimized_debug_session ───────────────────────────────────────────
795
796    #[test]
797    fn test_optimized_debug_session_creation() {
798        let selective_cfg = SelectiveDebugConfig::production_monitoring();
799        let perf_cfg = PerformanceConfig::default();
800        // Verify session was created without panicking.
801        let _session = optimized_debug_session(selective_cfg, perf_cfg);
802    }
803
804    #[test]
805    fn test_low_overhead_session_creation() {
806        let selective_cfg = SelectiveDebugConfig::production_monitoring();
807        let perf_cfg = PerformanceConfig {
808            low_overhead_mode: true,
809            ..PerformanceConfig::default()
810        };
811        // Just verify construction doesn't panic.
812        let _session = optimized_debug_session(selective_cfg, perf_cfg);
813    }
814
815    #[test]
816    fn test_ultra_low_overhead_session_creation() {
817        // Verify creation of the ultra-low overhead session doesn't panic.
818        let _session = ultra_low_overhead_session();
819    }
820}