memscope_rs/export/
system_optimizer.rs

1//! System optimizer module
2//!
3//! This module provides system resource detection, configuration optimization recommendations, and performance analysis tools.
4
5use crate::core::types::TrackingResult;
6use crate::export::fast_export_coordinator::{FastExportConfig, FastExportConfigBuilder};
7// use crate::export::performance_testing::{OptimizationTarget, PerformanceTestResult}; // Removed - using local definitions
8use crate::export::config_optimizer::OptimizationTarget;
9
10/// Performance test result
11#[derive(Debug, Clone)]
12pub struct PerformanceTestResult {
13    pub duration_ms: u64,
14    pub memory_usage_mb: f64,
15    pub success: bool,
16}
17
18use serde::{Deserialize, Serialize};
19
20/// System resource information
21#[derive(Debug, Clone, Serialize, Deserialize)]
22pub struct SystemResources {
23    /// Number of CPU cores
24    pub cpu_cores: usize,
25    /// Available memory (MB)
26    pub available_memory_mb: usize,
27    /// System load
28    pub system_load: f64,
29    /// Available disk space (MB)
30    pub disk_space_mb: usize,
31    /// System type
32    pub system_type: SystemType,
33}
34
35/// System type
36#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
37pub enum SystemType {
38    /// High performance server
39    HighPerformanceServer,
40    /// Development workstation
41    DevelopmentWorkstation,
42    /// Desktop
43    Desktop,
44    /// Laptop
45    Laptop,
46    /// Embedded system
47    Embedded,
48    /// Unknown system
49    Unknown,
50}
51
52/// Configuration recommendation
53#[derive(Debug, Clone, Serialize, Deserialize)]
54pub struct ConfigurationRecommendation {
55    /// Recommended shard size
56    pub recommended_shard_size: usize,
57    /// Recommended thread count
58    pub recommended_thread_count: usize,
59    /// Recommended buffer size
60    pub recommended_buffer_size: usize,
61    /// Optimization target
62    pub optimization_target: OptimizationTarget,
63    /// Expected performance gain
64    pub expected_performance_gain: f64,
65    /// Expected memory usage
66    pub expected_memory_usage_mb: f64,
67    /// Reasoning
68    pub reasoning: Vec<String>,
69    /// Configuration confidence (0.0-1.0)
70    pub confidence: f64,
71}
72
73/// Performance diagnosis result
74#[derive(Debug, Clone, Serialize, Deserialize)]
75pub struct PerformanceDiagnosis {
76    /// Diagnosis time (Unix timestamp)
77    pub diagnosis_time: u64,
78    /// System resource status
79    pub system_status: SystemResourceStatus,
80    /// Performance bottlenecks
81    pub bottlenecks: Vec<PerformanceBottleneck>,
82    /// Optimization suggestions
83    pub optimization_suggestions: Vec<OptimizationSuggestion>,
84    /// Overall health score (0-100)
85    pub health_score: u8,
86}
87
88/// System resource status
89#[derive(Debug, Clone, Serialize, Deserialize)]
90pub struct SystemResourceStatus {
91    /// CPU usage percentage
92    pub cpu_usage_percent: f64,
93    /// Memory usage percentage
94    pub memory_usage_percent: f64,
95    /// Disk usage percentage
96    pub disk_usage_percent: f64,
97    /// System load status
98    pub load_status: LoadStatus,
99}
100
101/// Load status
102#[derive(Debug, Clone, Serialize, Deserialize)]
103pub enum LoadStatus {
104    /// Low load
105    Low,
106    /// Medium load
107    Medium,
108    /// High load
109    High,
110    /// Overloaded
111    Overloaded,
112}
113
114/// Performance bottlenecks
115#[derive(Debug, Clone, Serialize, Deserialize)]
116pub struct PerformanceBottleneck {
117    /// Bottleneck type
118    pub bottleneck_type: BottleneckType,
119    /// Severity level (1-10)
120    pub severity: u8,
121    /// Description
122    pub description: String,
123    /// Impact
124    pub impact: String,
125    /// Suggested solutions
126    pub suggested_solutions: Vec<String>,
127}
128
129/// Bottleneck type
130#[derive(Debug, Clone, Serialize, Deserialize)]
131pub enum BottleneckType {
132    /// CPU bottleneck
133    Cpu,
134    /// Memory bottleneck
135    Memory,
136    /// I/O bottleneck
137    Io,
138    /// Network bottleneck
139    Network,
140    /// Configuration bottleneck
141    Configuration,
142}
143
144/// Optimization suggestions
145#[derive(Debug, Clone, Serialize, Deserialize)]
146pub struct OptimizationSuggestion {
147    /// suggestion type
148    pub suggestion_type: SuggestionType,
149    /// priority (1-10)
150    pub priority: u8,
151    /// title
152    pub title: String,
153    /// Detailed description
154    pub description: String,
155    /// expected impact
156    pub expected_impact: String,
157    /// implementation difficulty (1-10)
158    pub implementation_difficulty: u8,
159}
160
161/// Suggestion type
162#[derive(Debug, Clone, Serialize, Deserialize)]
163pub enum SuggestionType {
164    /// configuration tuning
165    ConfigurationTuning,
166    /// hardware upgrade
167    HardwareUpgrade,
168    /// software optimization
169    SoftwareOptimization,
170    /// environment tuning
171    EnvironmentTuning,
172}
173
174/// Optimization score
175#[derive(Debug, Clone, Serialize, Deserialize)]
176pub struct OptimizationScore {
177    /// performance score (1-10)
178    pub performance_score: u8,
179    /// memory efficiency (1-10)
180    pub memory_efficiency: u8,
181    /// stability score (1-10)
182    pub stability_score: u8,
183    /// overall score (1-10)
184    pub overall_score: u8,
185}
186
187/// System optimizer
188#[derive(Debug)]
189pub struct SystemOptimizer {
190    /// System resource information
191    system_resources: SystemResources,
192    /// performance history
193    performance_history: Vec<PerformanceTestResult>,
194    /// configuration validation rules
195    validation_rules: ConfigurationValidationRules,
196}
197
198/// Configuration validation rules
199#[derive(Debug, Clone)]
200pub struct ConfigurationValidationRules {
201    /// minimum shard size
202    pub min_shard_size: usize,
203    /// maximum shard size
204    pub max_shard_size: usize,
205    /// minimum thread count
206    pub min_thread_count: usize,
207    /// maximum thread count
208    pub max_thread_count: usize,
209    /// minimum buffer size
210    pub min_buffer_size: usize,
211    /// maximum buffer size
212    pub max_buffer_size: usize,
213    /// maximum memory limit (MB)
214    pub max_memory_limit_mb: usize,
215}
216
217impl Default for ConfigurationValidationRules {
218    fn default() -> Self {
219        Self {
220            min_shard_size: 100,
221            max_shard_size: 10000,
222            min_thread_count: 1,
223            max_thread_count: 32,
224            min_buffer_size: 16 * 1024,        // 16KB
225            max_buffer_size: 16 * 1024 * 1024, // 16MB
226            max_memory_limit_mb: 512,
227        }
228    }
229}
230
231impl SystemOptimizer {
232    /// Create new system optimizer
233    pub fn new() -> TrackingResult<Self> {
234        let system_resources = Self::detect_system_resources()?;
235
236        Ok(Self {
237            system_resources,
238            performance_history: Vec::new(),
239            validation_rules: ConfigurationValidationRules::default(),
240        })
241    }
242
243    /// Detect system resources
244    pub fn detect_system_resources() -> TrackingResult<SystemResources> {
245        let cpu_cores = num_cpus::get();
246        let available_memory_mb = Self::get_available_memory_mb();
247        let system_load = Self::get_system_load();
248        let disk_space_mb = Self::get_disk_space_mb();
249        let system_type = Self::classify_system_type(cpu_cores, available_memory_mb);
250
251        Ok(SystemResources {
252            cpu_cores,
253            available_memory_mb,
254            system_load,
255            disk_space_mb,
256            system_type,
257        })
258    }
259
260    /// Get available memory (MB)
261    fn get_available_memory_mb() -> usize {
262        // 简化实现 - 在实际应用中可以使用 sysinfo 等库获取准确信息
263        #[cfg(target_os = "linux")]
264        {
265            if let Ok(meminfo) = std::fs::read_to_string("/proc/meminfo") {
266                for line in meminfo.lines() {
267                    if line.starts_with("MemAvailable:") {
268                        if let Some(kb_str) = line.split_whitespace().nth(1) {
269                            if let Ok(kb) = kb_str.parse::<usize>() {
270                                return kb / 1024; // 转换为 MB
271                            }
272                        }
273                    }
274                }
275            }
276        }
277
278        // 回退到估算值
279        4096 // 假设 4GB 可用内存
280    }
281
282    /// Get system load
283    fn get_system_load() -> f64 {
284        // 简化实现 - 在实际应用中可以读取 /proc/loadavg
285        #[cfg(target_os = "linux")]
286        {
287            if let Ok(loadavg) = std::fs::read_to_string("/proc/loadavg") {
288                if let Some(load_str) = loadavg.split_whitespace().next() {
289                    if let Ok(load) = load_str.parse::<f64>() {
290                        return load;
291                    }
292                }
293            }
294        }
295
296        0.5 // 默认低负载
297    }
298
299    /// Get available disk space (MB)
300    fn get_disk_space_mb() -> usize {
301        // 简化实现 - 在实际应用中可以使用 statvfs 系统调用
302        10240 // 假设 10GB 可用空间
303    }
304
305    /// Classify system type
306    fn classify_system_type(cpu_cores: usize, memory_mb: usize) -> SystemType {
307        match (cpu_cores, memory_mb) {
308            (cores, mem) if cores >= 16 && mem >= 32768 => SystemType::HighPerformanceServer,
309            (cores, mem) if cores >= 8 && mem >= 16384 => SystemType::DevelopmentWorkstation,
310            (cores, mem) if cores >= 4 && mem >= 8192 => SystemType::Desktop,
311            (cores, mem) if cores >= 2 && mem >= 4096 => SystemType::Laptop,
312            (cores, mem) if cores >= 1 && mem >= 1024 => SystemType::Embedded,
313            _ => SystemType::Unknown,
314        }
315    }
316
317    /// Generate configuration recommendations
318    pub fn generate_configuration_recommendation(
319        &self,
320        target: OptimizationTarget,
321        dataset_size: Option<usize>,
322    ) -> ConfigurationRecommendation {
323        let dataset_size = dataset_size.unwrap_or(10000);
324
325        let (shard_size, thread_count, buffer_size, reasoning) = match target {
326            OptimizationTarget::Speed => self.optimize_for_speed(dataset_size),
327            OptimizationTarget::Memory => self.optimize_for_memory(dataset_size),
328            OptimizationTarget::Balanced => self.optimize_for_balance(dataset_size),
329        };
330
331        let expected_performance_gain =
332            self.estimate_performance_gain(&target, shard_size, thread_count);
333        let expected_memory_usage =
334            self.estimate_memory_usage(shard_size, thread_count, buffer_size);
335        let confidence = self.calculate_confidence(&target);
336
337        ConfigurationRecommendation {
338            recommended_shard_size: shard_size,
339            recommended_thread_count: thread_count,
340            recommended_buffer_size: buffer_size,
341            optimization_target: target,
342            expected_performance_gain,
343            expected_memory_usage_mb: expected_memory_usage,
344            reasoning,
345            confidence,
346        }
347    }
348
349    /// Speed optimization
350    fn optimize_for_speed(&self, dataset_size: usize) -> (usize, usize, usize, Vec<String>) {
351        let mut reasoning = Vec::new();
352
353        // based on system resources and dataset size
354        let base_shard_size = match self.system_resources.system_type {
355            SystemType::HighPerformanceServer => 5000,
356            SystemType::DevelopmentWorkstation => 3000,
357            SystemType::Desktop => 2000,
358            SystemType::Laptop => 1500,
359            SystemType::Embedded => 500,
360            SystemType::Unknown => 1000,
361        };
362
363        // based on dataset size
364        let shard_size = if dataset_size > 50000 {
365            base_shard_size * 2
366        } else if dataset_size > 20000 {
367            (base_shard_size as f64 * 1.5) as usize
368        } else {
369            base_shard_size
370        }
371        .min(self.validation_rules.max_shard_size);
372
373        reasoning.push(format!(
374            "basic {:?} system type, recommended shard size: {}",
375            self.system_resources.system_type, shard_size
376        ));
377
378        // based on system load
379        let thread_count = match self.system_resources.system_load {
380            load if load < 0.5 => self.system_resources.cpu_cores,
381            load if load < 1.0 => (self.system_resources.cpu_cores * 3 / 4).max(1),
382            load if load < 2.0 => (self.system_resources.cpu_cores / 2).max(1),
383            _ => (self.system_resources.cpu_cores / 4).max(1),
384        }
385        .min(self.validation_rules.max_thread_count);
386
387        reasoning.push(format!(
388            "basic system load {:.2}, recommended thread count: {}",
389            self.system_resources.system_load, thread_count
390        ));
391
392        // buffer size - large buffer size for better I/O performance
393        let buffer_size = match self.system_resources.available_memory_mb {
394            mem if mem >= 8192 => 2 * 1024 * 1024, // 2MB
395            mem if mem >= 4096 => 1024 * 1024,     // 1MB
396            mem if mem >= 2048 => 512 * 1024,      // 512KB
397            _ => 256 * 1024,                       // 256KB
398        }
399        .min(self.validation_rules.max_buffer_size);
400
401        reasoning.push(format!(
402            "basic available memory {} MB, recommended buffer size: {} KB",
403            self.system_resources.available_memory_mb,
404            buffer_size / 1024
405        ));
406
407        (shard_size, thread_count, buffer_size, reasoning)
408    }
409
410    /// Memory optimization
411    fn optimize_for_memory(&self, _dataset_size: usize) -> (usize, usize, usize, Vec<String>) {
412        let mut reasoning = Vec::new();
413
414        // small shard size to save memory
415        let shard_size = match self.system_resources.available_memory_mb {
416            mem if mem >= 4096 => 1000,
417            mem if mem >= 2048 => 750,
418            mem if mem >= 1024 => 500,
419            _ => 250,
420        }
421        .max(self.validation_rules.min_shard_size);
422
423        reasoning.push(format!(
424            "basic available memory {} MB, recommended shard size: {shard_size}",
425            self.system_resources.available_memory_mb
426        ));
427
428        // less thread count to reduce concurrent memory usage
429        let thread_count = match self.system_resources.available_memory_mb {
430            mem if mem >= 4096 => 4,
431            mem if mem >= 2048 => 2,
432            _ => 1,
433        }
434        .min(self.system_resources.cpu_cores / 2)
435        .max(1);
436
437        reasoning.push(format!(
438            "basic available memory {} MB, recommended thread count: {thread_count}",
439            self.system_resources.available_memory_mb
440        ));
441
442        // small buffer size to save memory
443        let buffer_size = match self.system_resources.available_memory_mb {
444            mem if mem >= 2048 => 256 * 1024, // 256KB
445            mem if mem >= 1024 => 128 * 1024, // 128KB
446            _ => 64 * 1024,                   // 64KB
447        }
448        .max(self.validation_rules.min_buffer_size);
449
450        reasoning.push(format!(
451            "basic available memory {} MB, recommended buffer size: {} KB",
452            self.system_resources.available_memory_mb,
453            buffer_size / 1024
454        ));
455
456        (shard_size, thread_count, buffer_size, reasoning)
457    }
458
459    /// balance optimization
460    fn optimize_for_balance(&self, dataset_size: usize) -> (usize, usize, usize, Vec<String>) {
461        let mut reasoning = Vec::new();
462
463        // balanced shard size
464        let shard_size = match (self.system_resources.cpu_cores, dataset_size) {
465            (cores, size) if cores >= 8 && size > 20000 => 2000,
466            (cores, size) if cores >= 4 && size > 10000 => 1500,
467            (cores, _) if cores >= 2 => 1000,
468            _ => 750,
469        }
470        .min(self.validation_rules.max_shard_size);
471
472        reasoning.push(format!(
473            "basic cpu cores {}, dataset size {dataset_size}, recommended shard size: {shard_size}",
474            self.system_resources.cpu_cores
475        ));
476
477        // balanced thread count
478        let thread_count = (self.system_resources.cpu_cores / 2)
479            .clamp(2, 6)
480            .min(self.validation_rules.max_thread_count);
481
482        reasoning.push(format!(
483            "basic cpu cores {}, dataset size {dataset_size}, recommended thread count: {thread_count}",
484            self.system_resources.cpu_cores,
485        ));
486
487        // balanced buffer size
488        let buffer_size = match self.system_resources.available_memory_mb {
489            mem if mem >= 4096 => 512 * 1024, // 512KB
490            mem if mem >= 2048 => 256 * 1024, // 256KB
491            _ => 128 * 1024,                  // 128KB
492        };
493
494        reasoning.push(format!(
495            "basic available memory {} MB, recommended buffer size: {} KB",
496            self.system_resources.available_memory_mb,
497            buffer_size / 1024
498        ));
499
500        (shard_size, thread_count, buffer_size, reasoning)
501    }
502
503    /// estimate performance gain
504    fn estimate_performance_gain(
505        &self,
506        target: &OptimizationTarget,
507        shard_size: usize,
508        thread_count: usize,
509    ) -> f64 {
510        let base_gain = match target {
511            OptimizationTarget::Speed => 3.0,
512            OptimizationTarget::Memory => 1.5,
513            OptimizationTarget::Balanced => 2.0,
514        };
515
516        // based on thread count
517        let thread_multiplier = (thread_count as f64).sqrt();
518
519        // based on shard size
520        let shard_multiplier = if shard_size > 2000 {
521            1.2
522        } else if shard_size < 500 {
523            0.8
524        } else {
525            1.0
526        };
527
528        base_gain * thread_multiplier * shard_multiplier
529    }
530
531    /// estimate memory usage
532    fn estimate_memory_usage(
533        &self,
534        shard_size: usize,
535        thread_count: usize,
536        buffer_size: usize,
537    ) -> f64 {
538        // base memory usage
539        let base_memory = 20.0; // 20MB base overhead
540
541        // shard memory usage (each allocation is about 500 bytes)
542        let shard_memory = (shard_size as f64 * 500.0 * thread_count as f64) / (1024.0 * 1024.0);
543
544        // buffer memory usage
545        let buffer_memory = (buffer_size as f64 * thread_count as f64) / (1024.0 * 1024.0);
546
547        base_memory + shard_memory + buffer_memory
548    }
549
550    /// calculate confidence
551    fn calculate_confidence(&self, target: &OptimizationTarget) -> f64 {
552        let mut confidence: f64 = 0.7; // base confidence
553
554        // based on system type adjustment
555        confidence += match self.system_resources.system_type {
556            SystemType::HighPerformanceServer => 0.2,
557            SystemType::DevelopmentWorkstation => 0.15,
558            SystemType::Desktop => 0.1,
559            SystemType::Laptop => 0.05,
560            SystemType::Embedded => -0.1,
561            SystemType::Unknown => -0.2,
562        };
563
564        // based on history data adjustment
565        if !self.performance_history.is_empty() {
566            confidence += 0.1;
567        }
568
569        // based on optimization target adjustment
570        confidence += match target {
571            OptimizationTarget::Balanced => 0.1,
572            OptimizationTarget::Speed => 0.05,
573            OptimizationTarget::Memory => 0.05,
574        };
575
576        confidence.clamp(0.0, 1.0)
577    }
578
579    /// validate configuration
580    pub fn validate_configuration(
581        &self,
582        _config: &FastExportConfigBuilder,
583    ) -> ConfigurationValidationResult {
584        let mut errors = Vec::new();
585        let mut warnings = Vec::new();
586        let mut suggestions = Vec::new();
587
588        // validate shard size
589        let shard_size = 1000; // default value, should be from config
590        if shard_size < self.validation_rules.min_shard_size {
591            errors.push(format!(
592                "shard size {} is less than minimum value {}",
593                shard_size, self.validation_rules.min_shard_size
594            ));
595        } else if shard_size > self.validation_rules.max_shard_size {
596            errors.push(format!(
597                "shard size {} is greater than maximum value {}",
598                shard_size, self.validation_rules.max_shard_size
599            ));
600        }
601
602        // validate thread count
603        let thread_count = num_cpus::get(); // default value, should be from config
604        if thread_count > self.system_resources.cpu_cores * 2 {
605            warnings.push(format!(
606                "thread count {thread_count} exceeds twice the number of CPU cores ({}), may cause context switch overhead",
607                self.system_resources.cpu_cores
608            ));
609        }
610
611        // validate memory usage
612        let estimated_memory = self.estimate_memory_usage(shard_size, thread_count, 256 * 1024);
613        if estimated_memory > self.system_resources.available_memory_mb as f64 * 0.8 {
614            errors.push(format!(
615                "estimated memory usage {:.1} MB exceeds 80% of available memory ({:.1} MB)",
616                estimated_memory,
617                self.system_resources.available_memory_mb as f64 * 0.8
618            ));
619        }
620
621        // generate optimization suggestions
622        if shard_size < 500 && self.system_resources.cpu_cores >= 4 {
623            suggestions.push("consider increasing shard size for better parallelism".to_string());
624        }
625
626        if thread_count == 1 && self.system_resources.cpu_cores > 2 {
627            suggestions
628                .push("consider enabling multi-threading for better performance".to_string());
629        }
630
631        ConfigurationValidationResult {
632            is_valid: errors.is_empty(),
633            errors,
634            warnings,
635            suggestions,
636            estimated_performance_impact: self
637                .estimate_configuration_impact(shard_size, thread_count),
638        }
639    }
640
641    /// estimate configuration impact
642    fn estimate_configuration_impact(
643        &self,
644        shard_size: usize,
645        thread_count: usize,
646    ) -> ConfigurationImpact {
647        let performance_score = match (shard_size, thread_count) {
648            (s, t) if s >= 2000 && t >= 4 => 9,
649            (s, t) if s >= 1000 && t >= 2 => 7,
650            (s, t) if s >= 500 && t >= 1 => 5,
651            _ => 3,
652        };
653
654        let memory_efficiency = if shard_size <= 1000 && thread_count <= 4 {
655            8
656        } else {
657            6
658        };
659        let stability_score = if thread_count <= self.system_resources.cpu_cores {
660            9
661        } else {
662            6
663        };
664
665        ConfigurationImpact {
666            performance_score,
667            memory_efficiency,
668            stability_score,
669            overall_score: (performance_score + memory_efficiency + stability_score) / 3,
670        }
671    }
672
673    /// diagnose performance issues
674    pub fn diagnose_performance(&self) -> PerformanceDiagnosis {
675        let system_status = self.get_system_resource_status();
676        let bottlenecks = self.identify_bottlenecks(&system_status);
677        let optimization_suggestions = self.generate_optimization_suggestions(&bottlenecks);
678        let health_score = self.calculate_health_score(&system_status, &bottlenecks);
679
680        PerformanceDiagnosis {
681            diagnosis_time: std::time::SystemTime::now()
682                .duration_since(std::time::UNIX_EPOCH)
683                .unwrap_or_default()
684                .as_secs(),
685            system_status,
686            bottlenecks,
687            optimization_suggestions,
688            health_score,
689        }
690    }
691
692    /// get system resource status
693    fn get_system_resource_status(&self) -> SystemResourceStatus {
694        let cpu_usage = self.get_cpu_usage();
695        let memory_usage =
696            (self.system_resources.available_memory_mb as f64 / 8192.0 * 100.0).min(100.0);
697        let disk_usage = 50.0; // simplified implementation
698
699        let load_status = match self.system_resources.system_load {
700            load if load < 1.0 => LoadStatus::Low,
701            load if load < 2.0 => LoadStatus::Medium,
702            load if load < 4.0 => LoadStatus::High,
703            _ => LoadStatus::Overloaded,
704        };
705
706        SystemResourceStatus {
707            cpu_usage_percent: cpu_usage,
708            memory_usage_percent: memory_usage,
709            disk_usage_percent: disk_usage,
710            load_status,
711        }
712    }
713
714    /// get CPU usage percentage
715    fn get_cpu_usage(&self) -> f64 {
716        // simplified implementation - based on system load estimation
717        (self.system_resources.system_load / self.system_resources.cpu_cores as f64 * 100.0)
718            .min(100.0)
719    }
720
721    /// identify performance bottlenecks
722    fn identify_bottlenecks(&self, status: &SystemResourceStatus) -> Vec<PerformanceBottleneck> {
723        let mut bottlenecks = Vec::new();
724
725        // CPU bottleneck detection
726        if status.cpu_usage_percent > 80.0 {
727            bottlenecks.push(PerformanceBottleneck {
728                bottleneck_type: BottleneckType::Cpu,
729                severity: if status.cpu_usage_percent > 95.0 {
730                    9
731                } else {
732                    7
733                },
734                description: format!("CPU usage is high: {:.1}%", status.cpu_usage_percent),
735                impact: "Export performance significantly degraded, response time increased"
736                    .to_string(),
737                suggested_solutions: vec![
738                    "reduce parallel thread count".to_string(),
739                    "increase shard size to reduce thread switch overhead".to_string(),
740                    "consider exporting when system load is low".to_string(),
741                ],
742            });
743        }
744
745        // memory bottleneck detection
746        if status.memory_usage_percent > 85.0 {
747            bottlenecks.push(PerformanceBottleneck {
748                bottleneck_type: BottleneckType::Memory,
749                severity: if status.memory_usage_percent > 95.0 {
750                    10
751                } else {
752                    8
753                },
754                description: format!("Memory usage is high: {:.1}%", status.memory_usage_percent),
755                impact: "possible memory underutilization, system may slow down or crash"
756                    .to_string(),
757                suggested_solutions: vec![
758                    "reduce shard size".to_string(),
759                    "reduce parallel thread count".to_string(),
760                    "reduce buffer size".to_string(),
761                    "enable streaming processing mode".to_string(),
762                ],
763            });
764        }
765
766        // configuration bottleneck detection
767        if self.system_resources.cpu_cores >= 8 && status.cpu_usage_percent < 30.0 {
768            bottlenecks.push(PerformanceBottleneck {
769                bottleneck_type: BottleneckType::Configuration,
770                severity: 5,
771                description: "CPU resource underutilized".to_string(),
772                impact: "Export performance suboptimal".to_string(),
773                suggested_solutions: vec![
774                    "add more threads".to_string(),
775                    "reduce shard size to increase parallelism".to_string(),
776                    "enable speed optimization mode".to_string(),
777                ],
778            });
779        }
780
781        bottlenecks
782    }
783
784    /// generate optimization suggestions
785    fn generate_optimization_suggestions(
786        &self,
787        bottlenecks: &[PerformanceBottleneck],
788    ) -> Vec<OptimizationSuggestion> {
789        let mut suggestions = Vec::new();
790
791        // based on bottleneck generate suggestions
792        for bottleneck in bottlenecks {
793            match bottleneck.bottleneck_type {
794                BottleneckType::Cpu => {
795                    suggestions.push(OptimizationSuggestion {
796                        suggestion_type: SuggestionType::ConfigurationTuning,
797                        priority: bottleneck.severity,
798                        title: "Optimize CPU usage".to_string(),
799                        description: "Adjust parallel configuration to optimize CPU usage"
800                            .to_string(),
801                        expected_impact: "Increase export speed by 20-40%".to_string(),
802                        implementation_difficulty: 3,
803                    });
804                }
805                BottleneckType::Memory => {
806                    suggestions.push(OptimizationSuggestion {
807                        suggestion_type: SuggestionType::ConfigurationTuning,
808                        priority: bottleneck.severity,
809                        title: "Optimize memory usage".to_string(),
810                        description: "Adjust shard size and buffer size to reduce memory usage"
811                            .to_string(),
812                        expected_impact: "Reduce memory usage by 30-50%".to_string(),
813                        implementation_difficulty: 2,
814                    });
815                }
816                BottleneckType::Configuration => {
817                    suggestions.push(OptimizationSuggestion {
818                        suggestion_type: SuggestionType::ConfigurationTuning,
819                        priority: bottleneck.severity,
820                        title: "Optimize configuration parameters".to_string(),
821                        description: "Adjust configuration to fully utilize system resources"
822                            .to_string(),
823                        expected_impact: "Increase overall performance by 15-30%".to_string(),
824                        implementation_difficulty: 1,
825                    });
826                }
827                _ => {}
828            }
829        }
830
831        // general optimization suggestions
832        if self.system_resources.system_type == SystemType::HighPerformanceServer {
833            suggestions.push(OptimizationSuggestion {
834                suggestion_type: SuggestionType::ConfigurationTuning,
835                priority: 6,
836                title: "Enable high performance mode".to_string(),
837                description: "Enable maximum performance configuration on high performance servers"
838                    .to_string(),
839                expected_impact: "Increase export speed by 50-80%".to_string(),
840                implementation_difficulty: 2,
841            });
842        }
843
844        suggestions
845    }
846
847    /// calculate health score
848    fn calculate_health_score(
849        &self,
850        status: &SystemResourceStatus,
851        bottlenecks: &[PerformanceBottleneck],
852    ) -> u8 {
853        let mut score = 100u8;
854
855        // based on resource usage rate to score
856        if status.cpu_usage_percent > 80.0 {
857            score = score.saturating_sub(20);
858        } else if status.cpu_usage_percent > 60.0 {
859            score = score.saturating_sub(10);
860        }
861
862        if status.memory_usage_percent > 85.0 {
863            score = score.saturating_sub(25);
864        } else if status.memory_usage_percent > 70.0 {
865            score = score.saturating_sub(15);
866        }
867
868        // based on bottleneck to score
869        for bottleneck in bottlenecks {
870            score = score.saturating_sub(bottleneck.severity * 2);
871        }
872
873        score.max(10) // minimum score is 10
874    }
875
876    /// add performance history data
877    pub fn add_performance_data(&mut self, result: PerformanceTestResult) {
878        self.performance_history.push(result);
879
880        // keep history data within a reasonable range
881        if self.performance_history.len() > 100 {
882            self.performance_history.remove(0);
883        }
884    }
885
886    /// get system resources
887    pub fn get_system_resources(&self) -> &SystemResources {
888        &self.system_resources
889    }
890
891    /// update system resources
892    pub fn refresh_system_resources(&mut self) -> TrackingResult<()> {
893        self.system_resources = Self::detect_system_resources()?;
894        Ok(())
895    }
896
897    /// run performance test
898    pub fn run_performance_test(&self, _config: &FastExportConfig) -> PerformanceTestResult {
899        // Simulate a performance test
900        let start = std::time::Instant::now();
901
902        // Simulate some work
903        std::thread::sleep(std::time::Duration::from_millis(10));
904
905        let duration = start.elapsed();
906
907        PerformanceTestResult {
908            duration_ms: duration.as_millis() as u64,
909            memory_usage_mb: 50.0, // Simulated memory usage
910            success: true,
911        }
912    }
913}
914
915impl Default for SystemOptimizer {
916    fn default() -> Self {
917        Self::new().unwrap_or_else(|_| Self {
918            system_resources: SystemResources {
919                cpu_cores: num_cpus::get(),
920                available_memory_mb: 4096,
921                system_load: 0.5,
922                disk_space_mb: 10240,
923                system_type: SystemType::Unknown,
924            },
925            performance_history: Vec::new(),
926            validation_rules: ConfigurationValidationRules::default(),
927        })
928    }
929}
930
931/// configuration validation result
932#[derive(Debug, Clone, Serialize, Deserialize)]
933pub struct ConfigurationValidationResult {
934    /// configuration is valid
935    pub is_valid: bool,
936    /// error list
937    pub errors: Vec<String>,
938    /// warning list
939    pub warnings: Vec<String>,
940    /// suggestion list
941    pub suggestions: Vec<String>,
942    /// estimated performance impact
943    pub estimated_performance_impact: ConfigurationImpact,
944}
945
946/// configuration impact
947#[derive(Debug, Clone, Serialize, Deserialize)]
948pub struct ConfigurationImpact {
949    /// performance score (1-10)
950    pub performance_score: u8,
951    /// memory efficiency (1-10)
952    pub memory_efficiency: u8,
953    /// stability score (1-10)
954    pub stability_score: u8,
955    /// overall score (1-10)
956    pub overall_score: u8,
957}
958
959#[cfg(test)]
960mod tests {
961    use super::*;
962
963    #[test]
964    fn test_system_resources_creation() {
965        let resources = SystemResources {
966            cpu_cores: 8,
967            available_memory_mb: 16384,
968            system_load: 0.5,
969            disk_space_mb: 1024000,
970            system_type: SystemType::DevelopmentWorkstation,
971        };
972
973        assert_eq!(resources.cpu_cores, 8);
974        assert_eq!(resources.available_memory_mb, 16384);
975        assert_eq!(resources.system_load, 0.5);
976        assert_eq!(resources.disk_space_mb, 1024000);
977        assert_eq!(resources.system_type, SystemType::DevelopmentWorkstation);
978    }
979
980    #[test]
981    fn test_system_type_variants() {
982        let types = vec![
983            SystemType::HighPerformanceServer,
984            SystemType::DevelopmentWorkstation,
985            SystemType::Desktop,
986            SystemType::Laptop,
987            SystemType::Embedded,
988            SystemType::Unknown,
989        ];
990
991        for system_type in types {
992            assert!(!format!("{system_type:?}").is_empty());
993        }
994    }
995
996    #[test]
997    fn test_configuration_recommendation() {
998        let recommendation = ConfigurationRecommendation {
999            recommended_shard_size: 1024,
1000            recommended_thread_count: 4,
1001            recommended_buffer_size: 8192,
1002            optimization_target: OptimizationTarget::Speed,
1003            expected_performance_gain: 0.25,
1004            expected_memory_usage_mb: 512.0,
1005            reasoning: vec![
1006                "High CPU core count detected".to_string(),
1007                "Sufficient memory available".to_string(),
1008            ],
1009            confidence: 0.85,
1010        };
1011
1012        assert_eq!(recommendation.recommended_shard_size, 1024);
1013        assert_eq!(recommendation.recommended_thread_count, 4);
1014        assert_eq!(recommendation.recommended_buffer_size, 8192);
1015        assert_eq!(recommendation.expected_performance_gain, 0.25);
1016        assert_eq!(recommendation.expected_memory_usage_mb, 512.0);
1017        assert_eq!(recommendation.reasoning.len(), 2);
1018        assert_eq!(recommendation.confidence, 0.85);
1019    }
1020
1021    #[test]
1022    fn test_performance_diagnosis() {
1023        let diagnosis = PerformanceDiagnosis {
1024            diagnosis_time: 1234567890,
1025            system_status: SystemResourceStatus {
1026                cpu_usage_percent: 45.0,
1027                memory_usage_percent: 60.0,
1028                disk_usage_percent: 30.0,
1029                load_status: LoadStatus::Medium,
1030            },
1031            bottlenecks: vec![PerformanceBottleneck {
1032                bottleneck_type: BottleneckType::Memory,
1033                severity: 6,
1034                description: "High memory usage detected".to_string(),
1035                impact: "May cause performance degradation".to_string(),
1036                suggested_solutions: vec![
1037                    "Increase buffer sizes".to_string(),
1038                    "Optimize memory allocation patterns".to_string(),
1039                ],
1040            }],
1041            optimization_suggestions: vec![OptimizationSuggestion {
1042                suggestion_type: SuggestionType::ConfigurationTuning,
1043                priority: 5,
1044                title: "Consider increasing thread count".to_string(),
1045                description: "Consider increasing thread count".to_string(),
1046                implementation_difficulty: 2,
1047                expected_impact: "Increase performance by 15%".to_string(),
1048            }],
1049            health_score: 75,
1050        };
1051
1052        assert_eq!(diagnosis.diagnosis_time, 1234567890);
1053        assert_eq!(diagnosis.system_status.cpu_usage_percent, 45.0);
1054        assert_eq!(diagnosis.system_status.memory_usage_percent, 60.0);
1055        assert_eq!(diagnosis.bottlenecks.len(), 1);
1056        assert_eq!(diagnosis.optimization_suggestions.len(), 1);
1057        assert_eq!(diagnosis.health_score, 75);
1058    }
1059
1060    #[test]
1061    fn test_system_resource_status() {
1062        let status = SystemResourceStatus {
1063            cpu_usage_percent: 80.0,
1064            memory_usage_percent: 90.0,
1065            disk_usage_percent: 95.0,
1066            load_status: LoadStatus::High,
1067        };
1068
1069        assert_eq!(status.cpu_usage_percent, 80.0);
1070        assert_eq!(status.memory_usage_percent, 90.0);
1071        assert_eq!(status.disk_usage_percent, 95.0);
1072        assert!(matches!(status.load_status, LoadStatus::High));
1073    }
1074
1075    #[test]
1076    fn test_load_status_variants() {
1077        let statuses = vec![
1078            LoadStatus::Low,
1079            LoadStatus::Medium,
1080            LoadStatus::High,
1081            LoadStatus::Overloaded,
1082        ];
1083
1084        for status in statuses {
1085            assert!(!format!("{:?}", status).is_empty());
1086        }
1087    }
1088
1089    #[test]
1090    fn test_performance_bottleneck() {
1091        let bottleneck = PerformanceBottleneck {
1092            bottleneck_type: BottleneckType::Cpu,
1093            severity: 8,
1094            description: "CPU utilization at 95%".to_string(),
1095            impact: "Significant performance impact".to_string(),
1096            suggested_solutions: vec![
1097                "Optimize algorithms".to_string(),
1098                "Reduce computational complexity".to_string(),
1099                "Consider hardware upgrade".to_string(),
1100            ],
1101        };
1102
1103        assert!(matches!(bottleneck.bottleneck_type, BottleneckType::Cpu));
1104        assert_eq!(bottleneck.severity, 8);
1105        assert!(bottleneck.description.contains("CPU"));
1106        assert_eq!(bottleneck.suggested_solutions.len(), 3);
1107    }
1108
1109    #[test]
1110    fn test_bottleneck_type_variants() {
1111        let types = vec![
1112            BottleneckType::Cpu,
1113            BottleneckType::Memory,
1114            BottleneckType::Io,
1115            BottleneckType::Network,
1116            BottleneckType::Configuration,
1117        ];
1118
1119        for bottleneck_type in types {
1120            assert!(!format!("{bottleneck_type:?}").is_empty());
1121        }
1122    }
1123
1124    #[test]
1125    fn test_performance_test_result() {
1126        let result = PerformanceTestResult {
1127            duration_ms: 1500,
1128            memory_usage_mb: 256.5,
1129            success: true,
1130        };
1131
1132        assert_eq!(result.duration_ms, 1500);
1133        assert_eq!(result.memory_usage_mb, 256.5);
1134        assert!(result.success);
1135    }
1136
1137    #[test]
1138    fn test_performance_test_result_failure() {
1139        let result = PerformanceTestResult {
1140            duration_ms: 0,
1141            memory_usage_mb: 0.0,
1142            success: false,
1143        };
1144
1145        assert_eq!(result.duration_ms, 0);
1146        assert_eq!(result.memory_usage_mb, 0.0);
1147        assert!(!result.success);
1148    }
1149
1150    #[test]
1151    fn test_system_optimizer_creation() {
1152        let optimizer = SystemOptimizer::new();
1153
1154        // Test that it can be created successfully
1155        assert!(!format!("{optimizer:?}").is_empty());
1156    }
1157
1158    #[test]
1159    fn test_system_optimizer_detect_resources() {
1160        let _optimizer = SystemOptimizer::new().expect("Failed to create optimizer");
1161        let resources =
1162            SystemOptimizer::detect_system_resources().expect("Failed to detect resources");
1163
1164        // Should return some reasonable values
1165        assert!(resources.cpu_cores > 0);
1166        assert!(resources.available_memory_mb > 0);
1167        assert!(resources.system_load >= 0.0);
1168        assert!(resources.disk_space_mb > 0);
1169    }
1170
1171    #[test]
1172    fn test_system_optimizer_generate_recommendations() {
1173        let optimizer = SystemOptimizer::new().expect("Failed to create optimizer");
1174        let _resources = SystemResources {
1175            cpu_cores: 8,
1176            available_memory_mb: 16384,
1177            system_load: 0.3,
1178            disk_space_mb: 1024000,
1179            system_type: SystemType::DevelopmentWorkstation,
1180        };
1181
1182        let recommendation =
1183            optimizer.generate_configuration_recommendation(OptimizationTarget::Speed, Some(10000));
1184
1185        assert!(recommendation.recommended_shard_size > 0);
1186        assert!(recommendation.recommended_thread_count > 0);
1187        assert!(recommendation.recommended_buffer_size > 0);
1188        assert!(recommendation.expected_performance_gain >= 0.0);
1189        assert!(recommendation.confidence >= 0.0 && recommendation.confidence <= 1.0);
1190        assert!(!recommendation.reasoning.is_empty());
1191    }
1192
1193    #[test]
1194    fn test_system_optimizer_diagnose_performance() {
1195        let optimizer = SystemOptimizer::new().expect("Failed to create optimizer");
1196        let diagnosis = optimizer.diagnose_performance();
1197
1198        assert!(diagnosis.diagnosis_time > 0);
1199        assert!(diagnosis.system_status.cpu_usage_percent >= 0.0);
1200        assert!(diagnosis.system_status.memory_usage_percent >= 0.0);
1201        assert!(diagnosis.system_status.disk_usage_percent >= 0.0);
1202        assert!(diagnosis.health_score <= 100);
1203    }
1204
1205    #[test]
1206    fn test_system_optimizer_run_performance_test() {
1207        let optimizer = SystemOptimizer::new().expect("Failed to create optimizer");
1208        let config = FastExportConfigBuilder::new()
1209            .shard_size(1024)
1210            .max_threads(Some(2))
1211            .buffer_size(4096)
1212            .build();
1213
1214        let result = optimizer.run_performance_test(&config);
1215
1216        // Should complete successfully
1217        assert!(result.success);
1218        assert!(result.memory_usage_mb >= 0.0);
1219    }
1220
1221    #[test]
1222    fn test_system_optimizer_serialization() {
1223        let resources = SystemResources {
1224            cpu_cores: 4,
1225            available_memory_mb: 8192,
1226            system_load: 0.7,
1227            disk_space_mb: 512000,
1228            system_type: SystemType::Laptop,
1229        };
1230
1231        // Test that it can be serialized and deserialized
1232        let serialized = serde_json::to_string(&resources).expect("Failed to serialize");
1233        let deserialized: SystemResources =
1234            serde_json::from_str(&serialized).expect("Failed to deserialize");
1235
1236        assert_eq!(deserialized.cpu_cores, 4);
1237        assert_eq!(deserialized.available_memory_mb, 8192);
1238        assert_eq!(deserialized.system_load, 0.7);
1239        assert_eq!(deserialized.system_type, SystemType::Laptop);
1240    }
1241
1242    #[test]
1243    fn test_configuration_recommendation_serialization() {
1244        let recommendation = ConfigurationRecommendation {
1245            recommended_shard_size: 2048,
1246            recommended_thread_count: 6,
1247            recommended_buffer_size: 16384,
1248            optimization_target: OptimizationTarget::Memory,
1249            expected_performance_gain: 0.20,
1250            expected_memory_usage_mb: 1024.0,
1251            reasoning: vec!["Test reasoning".to_string()],
1252            confidence: 0.90,
1253        };
1254
1255        let serialized = serde_json::to_string(&recommendation).expect("Failed to serialize");
1256        let deserialized: ConfigurationRecommendation =
1257            serde_json::from_str(&serialized).expect("Failed to deserialize");
1258
1259        assert_eq!(deserialized.recommended_shard_size, 2048);
1260        assert_eq!(deserialized.recommended_thread_count, 6);
1261        assert_eq!(deserialized.expected_performance_gain, 0.20);
1262        assert_eq!(deserialized.confidence, 0.90);
1263    }
1264
1265    #[test]
1266    fn test_performance_diagnosis_serialization() {
1267        let diagnosis = PerformanceDiagnosis {
1268            diagnosis_time: 9876543210,
1269            system_status: SystemResourceStatus {
1270                cpu_usage_percent: 55.5,
1271                memory_usage_percent: 70.2,
1272                disk_usage_percent: 40.8,
1273                load_status: LoadStatus::Medium,
1274            },
1275            bottlenecks: vec![],
1276            optimization_suggestions: vec![],
1277            health_score: 80,
1278        };
1279
1280        let serialized = serde_json::to_string(&diagnosis).expect("Failed to serialize");
1281        let deserialized: PerformanceDiagnosis =
1282            serde_json::from_str(&serialized).expect("Failed to deserialize");
1283
1284        assert_eq!(deserialized.diagnosis_time, 9876543210);
1285        assert_eq!(deserialized.system_status.cpu_usage_percent, 55.5);
1286        assert_eq!(deserialized.health_score, 80);
1287    }
1288
1289    #[test]
1290    fn test_optimization_target_variants() {
1291        // Test that all optimization targets can be created and debugged
1292        let targets = vec![
1293            OptimizationTarget::Speed,
1294            OptimizationTarget::Memory,
1295            OptimizationTarget::Balanced,
1296        ];
1297
1298        for target in targets {
1299            assert!(!format!("{:?}", target).is_empty());
1300        }
1301    }
1302
1303    #[test]
1304    fn test_edge_case_zero_resources() {
1305        let _resources = SystemResources {
1306            cpu_cores: 0,
1307            available_memory_mb: 0,
1308            system_load: 0.0,
1309            disk_space_mb: 0,
1310            system_type: SystemType::Unknown,
1311        };
1312
1313        let optimizer = SystemOptimizer::new().expect("Failed to create optimizer");
1314        let recommendation = optimizer
1315            .generate_configuration_recommendation(OptimizationTarget::Balanced, Some(10000));
1316
1317        // Should handle edge case gracefully
1318        assert!(recommendation.recommended_shard_size > 0); // Should have fallback values
1319        assert!(recommendation.recommended_thread_count > 0);
1320        assert!(recommendation.confidence >= 0.0);
1321    }
1322
1323    #[test]
1324    fn test_high_load_scenario() {
1325        let resources = SystemResources {
1326            cpu_cores: 16,
1327            available_memory_mb: 65536,
1328            system_load: 0.95, // Very high load
1329            disk_space_mb: 2048000,
1330            system_type: SystemType::HighPerformanceServer,
1331        };
1332
1333        let optimizer = SystemOptimizer::new().expect("Failed to create optimizer");
1334        let recommendation =
1335            optimizer.generate_configuration_recommendation(OptimizationTarget::Speed, Some(10000));
1336
1337        // Should adapt to high-performance scenario
1338        assert!(recommendation.recommended_thread_count <= resources.cpu_cores);
1339        assert!(recommendation.expected_performance_gain >= 0.0);
1340        assert!(!recommendation.reasoning.is_empty());
1341    }
1342
1343    #[test]
1344    fn test_optimization_score_creation() {
1345        let score = OptimizationScore {
1346            performance_score: 8,
1347            memory_efficiency: 7,
1348            stability_score: 9,
1349            overall_score: 8,
1350        };
1351
1352        assert_eq!(score.performance_score, 8);
1353        assert_eq!(score.memory_efficiency, 7);
1354        assert_eq!(score.stability_score, 9);
1355        assert_eq!(score.overall_score, 8);
1356    }
1357
1358    #[test]
1359    fn test_optimization_score_debug() {
1360        let score = OptimizationScore {
1361            performance_score: 5,
1362            memory_efficiency: 6,
1363            stability_score: 7,
1364            overall_score: 6,
1365        };
1366
1367        let debug_str = format!("{:?}", score);
1368        assert!(debug_str.contains("performance_score: 5"));
1369        assert!(debug_str.contains("memory_efficiency: 6"));
1370        assert!(debug_str.contains("stability_score: 7"));
1371        assert!(debug_str.contains("overall_score: 6"));
1372    }
1373}