1use crate::error::{CoreError, CoreResult};
63use std::collections::{HashMap, VecDeque};
64use std::sync::{Arc, Mutex, RwLock};
65use std::time::{Duration, Instant, SystemTime};
66
67use serde::{Deserialize, Serialize};
68
69#[derive(Debug, Clone, Serialize, Deserialize)]
71pub struct OptimizationConfig {
72 pub goal: OptimizationGoal,
74 pub learningrate: f64,
76 pub adaptation_interval: Duration,
78 pub history_retention: Duration,
80 pub confidence_threshold: f64,
82 pub max_adjustment_rate: f64,
84 pub enable_prediction: bool,
86 pub enable_multi_objective: bool,
88 pub resource_constraints: ResourceConstraints,
90 pub enable_rollback: bool,
92 pub monitoring_window: Duration,
94}
95
96impl Default for OptimizationConfig {
97 fn default() -> Self {
98 Self {
99 goal: OptimizationGoal::Balanced,
100 learningrate: 0.01,
101 adaptation_interval: Duration::from_secs(60),
102 history_retention: Duration::from_secs(24 * 60 * 60), confidence_threshold: 0.95,
104 max_adjustment_rate: 0.1, enable_prediction: true,
106 enable_multi_objective: true,
107 resource_constraints: ResourceConstraints::default(),
108 enable_rollback: true,
109 monitoring_window: Duration::from_secs(300), }
111 }
112}
113
114impl OptimizationConfig {
115 pub fn production() -> Self {
117 Self {
118 goal: OptimizationGoal::Performance,
119 learningrate: 0.005, adaptation_interval: Duration::from_secs(300), confidence_threshold: 0.99, max_adjustment_rate: 0.05, enable_rollback: true,
124 ..Default::default()
125 }
126 }
127
128 pub fn development() -> Self {
130 Self {
131 goal: OptimizationGoal::Development,
132 learningrate: 0.02, adaptation_interval: Duration::from_secs(30),
134 confidence_threshold: 0.85,
135 max_adjustment_rate: 0.2, ..Default::default()
137 }
138 }
139
140 pub fn memory_optimized() -> Self {
142 Self {
143 goal: OptimizationGoal::MemoryEfficiency,
144 resource_constraints: ResourceConstraints {
145 max_memory_usage: Some(1024 * 1024 * 1024), max_cpu_usage: Some(0.8),
147 ..Default::default()
148 },
149 ..Default::default()
150 }
151 }
152
153 pub fn with_goal(mut self, goal: OptimizationGoal) -> Self {
155 self.goal = goal;
156 self
157 }
158
159 pub fn with_learningrate(mut self, rate: f64) -> Self {
161 self.learningrate = rate.clamp(0.001, 0.1);
162 self
163 }
164
165 pub fn with_adaptation_interval(mut self, interval: Duration) -> Self {
167 self.adaptation_interval = interval;
168 self
169 }
170
171 pub fn with_confidence_threshold(mut self, threshold: f64) -> Self {
173 self.confidence_threshold = threshold.clamp(0.5, 0.999);
174 self
175 }
176
177 pub fn with_prediction(mut self, enable: bool) -> Self {
179 self.enable_prediction = enable;
180 self
181 }
182
183 pub fn with_resource_constraints(mut self, constraints: ResourceConstraints) -> Self {
185 self.resource_constraints = constraints;
186 self
187 }
188}
189
190#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
192pub enum OptimizationGoal {
193 Performance,
195 MemoryEfficiency,
197 EnergyEfficiency,
199 Balanced,
201 Development,
203 Custom(Vec<ObjectiveWeight>),
205}
206
207#[derive(Debug, Clone, Serialize, Deserialize)]
209pub struct ObjectiveWeight {
210 pub name: String,
212 pub weight: f64,
214 pub priority: Priority,
216}
217
218impl PartialEq for ObjectiveWeight {
219 fn eq(&self, other: &Self) -> bool {
220 self.name == other.name
221 && (self.weight - other.weight).abs() < f64::EPSILON
222 && self.priority == other.priority
223 }
224}
225
226impl Eq for ObjectiveWeight {}
227
228#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
230pub enum Priority {
231 Low,
233 Medium,
235 High,
237 Critical,
239}
240
241#[derive(Debug, Clone, Serialize, Deserialize)]
243pub struct ResourceConstraints {
244 pub max_memory_usage: Option<usize>,
246 pub max_cpu_usage: Option<f64>,
248 pub max_networkbandwidth: Option<usize>,
250 pub max_disk_io: Option<usize>,
252 pub max_threads: Option<usize>,
254 pub max_energy_consumption: Option<f64>,
256}
257
258impl Default for ResourceConstraints {
259 fn default() -> Self {
260 Self {
261 max_memory_usage: None,
262 max_cpu_usage: Some(0.9), max_networkbandwidth: None,
264 max_disk_io: None,
265 max_threads: Some({
266 #[cfg(feature = "num_cpus")]
267 {
268 num_cpus::get()
269 }
270 #[cfg(not(feature = "num_cpus"))]
271 {
272 4 }
274 }),
275 max_energy_consumption: None,
276 }
277 }
278}
279
280#[derive(Debug, Clone, Serialize, Deserialize)]
282pub struct WorkloadProfile {
283 pub name: String,
285 pub data_size: usize,
287 pub compute_intensity: f64,
289 pub memory_pattern: MemoryPattern,
291 pub parallelism_profile: ParallelismProfile,
293 pub io_profile: IOProfile,
295 pub workload_type: WorkloadType,
297 pub expected_duration: Option<Duration>,
299 pub priority: Priority,
301}
302
303#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
305pub enum MemoryPattern {
306 Sequential,
308 Random,
310 Strided,
312 Mixed,
314 CacheFriendly,
316}
317
318#[derive(Debug, Clone, Serialize, Deserialize)]
320pub struct ParallelismProfile {
321 pub parallelizable: bool,
323 pub optimal_threads: Option<usize>,
325 pub sync_overhead: f64,
327 pub load_balance: LoadBalanceType,
329}
330
331#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
333pub enum LoadBalanceType {
334 Even,
336 Uneven,
338 Dynamic,
340 WorkStealing,
342}
343
344#[derive(Debug, Clone, Serialize, Deserialize)]
346pub struct IOProfile {
347 pub intensity: f64,
349 pub io_type: IOType,
351 pub read_write_ratio: f64,
353 pub preferred_buffersize: Option<usize>,
355}
356
357#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
359pub enum IOType {
360 Disk,
362 Network,
364 Memory,
366 Mixed,
368 None,
370}
371
372#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
374pub enum WorkloadType {
375 ComputeIntensive,
377 MemoryIntensive,
379 IOIntensive,
381 NetworkIntensive,
383 Balanced,
385 Interactive,
387 Batch,
389 RealTime,
391 Custom(String),
393}
394
395impl WorkloadProfile {
396 pub fn builder() -> WorkloadProfileBuilder {
398 WorkloadProfileBuilder::new()
399 }
400
401 pub fn get_optimization_hints(&self) -> OptimizationHints {
403 OptimizationHints {
404 preferred_chunk_size: self.calculate_optimal_chunk_size(),
405 preferred_thread_count: self.parallelism_profile.optimal_threads,
406 memory_allocation_strategy: self.get_memory_strategy(),
407 caching_strategy: self.get_caching_strategy(),
408 io_strategy: self.get_io_strategy(),
409 algorithm_preferences: self.get_algorithm_preferences(),
410 }
411 }
412
413 fn calculate_optimal_chunk_size(&self) -> Option<usize> {
415 match self.memory_pattern {
416 MemoryPattern::Sequential => Some((self.data_size / 1000).max(1024)),
417 MemoryPattern::Random => Some(4096), MemoryPattern::CacheFriendly => Some(64 * 1024), _ => None,
420 }
421 }
422
423 fn get_memory_strategy(&self) -> MemoryStrategy {
425 match self.workload_type {
426 WorkloadType::MemoryIntensive => MemoryStrategy::PreAllocate,
427 WorkloadType::Interactive => MemoryStrategy::LazyAllocation,
428 WorkloadType::Batch => MemoryStrategy::BulkAllocation,
429 _ => MemoryStrategy::Adaptive,
430 }
431 }
432
433 fn get_caching_strategy(&self) -> CachingStrategy {
435 match self.memory_pattern {
436 MemoryPattern::Sequential => CachingStrategy::Prefetch,
437 MemoryPattern::Random => CachingStrategy::LRU,
438 MemoryPattern::CacheFriendly => CachingStrategy::Aggressive,
439 _ => CachingStrategy::Conservative,
440 }
441 }
442
443 fn get_io_strategy(&self) -> IOStrategy {
445 match self.io_profile.io_type {
446 IOType::Disk => IOStrategy::Buffered,
447 IOType::Network => IOStrategy::Async,
448 IOType::Memory => IOStrategy::Direct,
449 IOType::Mixed => IOStrategy::Adaptive,
450 IOType::None => IOStrategy::Minimal,
451 }
452 }
453
454 fn get_algorithm_preferences(&self) -> Vec<AlgorithmPreference> {
456 let mut preferences = Vec::new();
457
458 match self.workload_type {
459 WorkloadType::ComputeIntensive => {
460 preferences.push(AlgorithmPreference::Simd);
461 preferences.push(AlgorithmPreference::Parallel);
462 }
463 WorkloadType::MemoryIntensive => {
464 preferences.push(AlgorithmPreference::CacheEfficient);
465 preferences.push(AlgorithmPreference::MemoryEfficient);
466 }
467 WorkloadType::Interactive => {
468 preferences.push(AlgorithmPreference::LowLatency);
469 preferences.push(AlgorithmPreference::Responsive);
470 }
471 _ => {
472 preferences.push(AlgorithmPreference::Balanced);
473 }
474 }
475
476 preferences
477 }
478}
479
480pub struct WorkloadProfileBuilder {
482 name: String,
483 data_size: usize,
484 compute_intensity: f64,
485 memory_pattern: MemoryPattern,
486 parallelism_profile: ParallelismProfile,
487 io_profile: IOProfile,
488 workload_type: WorkloadType,
489 expected_duration: Option<Duration>,
490 priority: Priority,
491}
492
493impl WorkloadProfileBuilder {
494 fn new() -> Self {
495 Self {
496 name: "default_workload".to_string(),
497 data_size: 1024,
498 compute_intensity: 0.5,
499 memory_pattern: MemoryPattern::Mixed,
500 parallelism_profile: ParallelismProfile {
501 parallelizable: true,
502 optimal_threads: None,
503 sync_overhead: 0.1,
504 load_balance: LoadBalanceType::Even,
505 },
506 io_profile: IOProfile {
507 intensity: 0.1,
508 io_type: IOType::None,
509 read_write_ratio: 0.8,
510 preferred_buffersize: None,
511 },
512 workload_type: WorkloadType::Balanced,
513 expected_duration: None,
514 priority: Priority::Medium,
515 }
516 }
517
518 pub fn with_name(mut self, name: &str) -> Self {
520 self.name = name.to_string();
521 self
522 }
523
524 pub fn with_data_size(mut self, size: usize) -> Self {
526 self.data_size = size;
527 self
528 }
529
530 pub fn with_compute_intensity(mut self, intensity: f64) -> Self {
532 self.compute_intensity = intensity.clamp(0.0, 1.0);
533 self
534 }
535
536 pub fn with_memory_pattern(mut self, pattern: MemoryPattern) -> Self {
538 self.memory_pattern = pattern;
539 self
540 }
541
542 pub fn with_workload_type(mut self, workloadtype: WorkloadType) -> Self {
544 self.workload_type = workloadtype;
545 self
546 }
547
548 pub fn with_priority(mut self, priority: Priority) -> Self {
550 self.priority = priority;
551 self
552 }
553
554 pub fn with_expected_duration(mut self, duration: Duration) -> Self {
556 self.expected_duration = Some(duration);
557 self
558 }
559
560 pub fn with_parallelism(
562 mut self,
563 parallelizable: bool,
564 optimal_threads: Option<usize>,
565 ) -> Self {
566 self.parallelism_profile.parallelizable = parallelizable;
567 self.parallelism_profile.optimal_threads = optimal_threads;
568 self
569 }
570
571 pub fn with_io_profile(mut self, intensity: f64, iotype: IOType) -> Self {
573 self.io_profile.intensity = intensity.clamp(0.0, 1.0);
574 self.io_profile.io_type = iotype;
575 self
576 }
577
578 pub fn build(self) -> WorkloadProfile {
580 WorkloadProfile {
581 name: self.name,
582 data_size: self.data_size,
583 compute_intensity: self.compute_intensity,
584 memory_pattern: self.memory_pattern,
585 parallelism_profile: self.parallelism_profile,
586 io_profile: self.io_profile,
587 workload_type: self.workload_type,
588 expected_duration: self.expected_duration,
589 priority: self.priority,
590 }
591 }
592}
593
594#[derive(Debug, Clone)]
596pub struct OptimizationHints {
597 pub preferred_chunk_size: Option<usize>,
599 pub preferred_thread_count: Option<usize>,
601 pub memory_allocation_strategy: MemoryStrategy,
603 pub caching_strategy: CachingStrategy,
605 pub io_strategy: IOStrategy,
607 pub algorithm_preferences: Vec<AlgorithmPreference>,
609}
610
611#[derive(Debug, Clone, Copy, PartialEq, Eq)]
613pub enum MemoryStrategy {
614 PreAllocate,
616 LazyAllocation,
618 BulkAllocation,
620 Adaptive,
622}
623
624#[derive(Debug, Clone, Copy, PartialEq, Eq)]
626pub enum CachingStrategy {
627 Aggressive,
629 Conservative,
631 LRU,
633 Prefetch,
635 None,
637}
638
639#[derive(Debug, Clone, Copy, PartialEq, Eq)]
641pub enum IOStrategy {
642 Buffered,
644 Async,
646 Direct,
648 Adaptive,
650 Minimal,
652}
653
654#[derive(Debug, Clone, Copy, PartialEq, Eq)]
656pub enum AlgorithmPreference {
657 Simd,
659 Parallel,
661 CacheEfficient,
663 MemoryEfficient,
665 LowLatency,
667 Responsive,
669 Balanced,
671}
672
673#[derive(Debug, Clone, Serialize, Deserialize)]
675pub struct PerformanceMetric {
676 pub name: String,
678 pub value: f64,
680 pub target: Option<f64>,
682 pub timestamp: SystemTime,
684 pub confidence: f64,
686 pub trend: Trend,
688}
689
690#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
692pub enum Trend {
693 Improving,
695 Stable,
697 Degrading,
699 Unknown,
701}
702
703#[derive(Debug, Clone, Serialize, Deserialize)]
705pub struct OptimizationRecommendation {
706 pub parameter: String,
708 pub current_value: String,
710 pub suggested_value: String,
712 pub expected_impact: Impact,
714 pub confidence: f64,
716 pub rationale: String,
718 pub risk_level: RiskLevel,
720}
721
722#[derive(Debug, Clone, Serialize, Deserialize)]
724pub struct Impact {
725 pub performance_improvement: f64,
727 pub memory_change: f64,
729 pub energy_change: f64,
731 pub benefit_score: f64,
733}
734
735#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
737pub enum RiskLevel {
738 Low,
740 Medium,
742 High,
744 Critical,
746}
747
748pub struct AdaptiveOptimizer {
750 config: OptimizationConfig,
752 workloads: Arc<RwLock<HashMap<String, WorkloadProfile>>>,
754 performance_history: Arc<Mutex<HashMap<String, VecDeque<PerformanceMetric>>>>,
756 current_parameters: Arc<RwLock<HashMap<String, f64>>>,
758 state: OptimizerState,
760 last_optimization: Instant,
762 baseline_metrics: Arc<Mutex<HashMap<String, f64>>>,
764 active_recommendations: Arc<Mutex<Vec<OptimizationRecommendation>>>,
766 #[allow(dead_code)]
768 learning_history: Arc<Mutex<VecDeque<LearningDataPoint>>>,
769}
770
771#[derive(Debug, Clone, Copy, PartialEq, Eq)]
773pub enum OptimizerState {
774 Stopped,
776 Learning,
778 Optimizing,
780 Paused,
782 Error,
784}
785
786#[derive(Debug, Clone)]
788struct LearningDataPoint {
789 #[allow(dead_code)]
791 parameters: HashMap<String, f64>,
792 #[allow(dead_code)]
794 metrics: HashMap<String, f64>,
795 #[allow(dead_code)]
797 timestamp: SystemTime,
798 #[allow(dead_code)]
800 workload: String,
801}
802
803impl AdaptiveOptimizer {
804 pub fn new(config: OptimizationConfig) -> CoreResult<Self> {
806 Ok(Self {
807 config,
808 workloads: Arc::new(RwLock::new(HashMap::new())),
809 performance_history: Arc::new(Mutex::new(HashMap::new())),
810 current_parameters: Arc::new(RwLock::new(HashMap::new())),
811 state: OptimizerState::Stopped,
812 last_optimization: Instant::now(),
813 baseline_metrics: Arc::new(Mutex::new(HashMap::new())),
814 active_recommendations: Arc::new(Mutex::new(Vec::new())),
815 learning_history: Arc::new(Mutex::new(VecDeque::new())),
816 })
817 }
818
819 pub fn register_workload(&mut self, workload: WorkloadProfile) -> CoreResult<()> {
821 if let Ok(mut workloads) = self.workloads.write() {
822 workloads.insert(workload.name.clone(), workload);
823 }
824 Ok(())
825 }
826
827 pub fn start_optimization(&mut self) -> CoreResult<()> {
829 if self.state == OptimizerState::Optimizing {
830 return Ok(());
831 }
832
833 self.collectbaseline_metrics()?;
835
836 self.state = OptimizerState::Learning;
837 self.last_optimization = Instant::now();
838
839 println!("🚀 Adaptive optimizer started in learning mode");
840 Ok(())
841 }
842
843 pub fn stop_optimization(&mut self) -> CoreResult<()> {
845 self.state = OptimizerState::Stopped;
846 println!("🛑 Adaptive optimizer stopped");
847 Ok(())
848 }
849
850 pub fn record_metric(
852 &mut self,
853 workload: &str,
854 metricname: &str,
855 value: f64,
856 ) -> CoreResult<()> {
857 let metric = PerformanceMetric {
858 name: metricname.to_string(),
859 value,
860 target: None,
861 timestamp: SystemTime::now(),
862 confidence: 1.0,
863 trend: self.calculate_trend(workload, metricname, value),
864 };
865
866 if let Ok(mut history) = self.performance_history.lock() {
867 let workload_metrics = history.entry(workload.to_string()).or_default();
868 workload_metrics.push_back(metric);
869
870 while workload_metrics.len() > 1000 {
872 workload_metrics.pop_front();
873 }
874 }
875
876 if self.last_optimization.elapsed() >= self.config.adaptation_interval {
878 self.run_optimization_cycle()?;
879 }
880
881 Ok(())
882 }
883
884 pub fn get_recommendations(&self) -> CoreResult<Vec<OptimizationRecommendation>> {
886 self.active_recommendations
887 .lock()
888 .map(|recs| recs.clone())
889 .map_err(|_| CoreError::from(std::io::Error::other("Failed to access recommendations")))
890 }
891
892 pub fn apply_recommendation(&mut self, recommendationid: usize) -> CoreResult<()> {
894 let recommendation = {
895 let mut recs = self.active_recommendations.lock().map_err(|_| {
896 CoreError::from(std::io::Error::other("Failed to access recommendations"))
897 })?;
898
899 if recommendationid >= recs.len() {
900 return Err(CoreError::from(std::io::Error::new(
901 std::io::ErrorKind::InvalidInput,
902 "Recommendation ID out of range",
903 )));
904 }
905
906 recs.remove(recommendationid)
907 };
908
909 if let Ok(mut params) = self.current_parameters.write() {
911 if let Ok(suggested_value) = recommendation.suggested_value.parse::<f64>() {
912 params.insert(recommendation.parameter.clone(), suggested_value);
913 println!(
914 "✅ Applied optimization: {} = {}",
915 recommendation.parameter, recommendation.suggested_value
916 );
917 }
918 }
919
920 Ok(())
921 }
922
923 pub fn get_statistics(&self) -> OptimizerStatistics {
925 let workload_count = self.workloads.read().map(|w| w.len()).unwrap_or(0);
926 let recommendation_count = self
927 .active_recommendations
928 .lock()
929 .map(|r| r.len())
930 .unwrap_or(0);
931 let parameter_count = self.current_parameters.read().map(|p| p.len()).unwrap_or(0);
932
933 OptimizerStatistics {
934 state: self.state,
935 registered_workloads: workload_count,
936 active_recommendations: recommendation_count,
937 optimized_parameters: parameter_count,
938 last_optimization: self.last_optimization,
939 uptime: self.last_optimization.elapsed(),
940 }
941 }
942
943 pub fn get_optimization_hints(&self, workloadname: &str) -> CoreResult<OptimizationHints> {
945 if let Ok(workloads) = self.workloads.read() {
946 if let Some(workload) = workloads.get(workloadname) {
947 return Ok(workload.get_optimization_hints());
948 }
949 }
950
951 Err(CoreError::from(std::io::Error::new(
952 std::io::ErrorKind::NotFound,
953 format!("Workload '{workloadname}' not found"),
954 )))
955 }
956
957 fn collectbaseline_metrics(&mut self) -> CoreResult<()> {
959 let mut baseline = HashMap::new();
961 baseline.insert("cpu_usage".to_string(), 45.0);
962 baseline.insert("memory_usage".to_string(), 1024.0);
963 baseline.insert("execution_time".to_string(), 100.0);
964 baseline.insert("throughput".to_string(), 1000.0);
965
966 if let Ok(mut metrics) = self.baseline_metrics.lock() {
967 *metrics = baseline;
968 }
969
970 Ok(())
971 }
972
973 fn calculate_trend(&self, workload: &str, metricname: &str, value: f64) -> Trend {
975 if let Ok(history) = self.performance_history.lock() {
976 if let Some(workload_metrics) = history.get(workload) {
977 let recent_values: Vec<f64> = workload_metrics
978 .iter()
979 .filter(|m| m.name == metricname)
980 .rev()
981 .take(10)
982 .map(|m| m.value)
983 .collect();
984
985 if recent_values.len() < 3 {
986 return Trend::Unknown;
987 }
988
989 let avg_old =
990 recent_values[5..].iter().sum::<f64>() / (recent_values.len() - 5) as f64;
991 let avg_new = recent_values[..5].iter().sum::<f64>() / 5.0;
992
993 let change_percent = (avg_new - avg_old) / avg_old * 100.0;
994
995 if change_percent > 5.0 {
996 Trend::Improving
997 } else if change_percent < -5.0 {
998 Trend::Degrading
999 } else {
1000 Trend::Stable
1001 }
1002 } else {
1003 Trend::Unknown
1004 }
1005 } else {
1006 Trend::Unknown
1007 }
1008 }
1009
1010 fn run_optimization_cycle(&mut self) -> CoreResult<()> {
1012 if self.state == OptimizerState::Learning {
1013 if self.has_sufficient_learning_data() {
1015 self.state = OptimizerState::Optimizing;
1016 println!("🧠Transitioning to optimization mode");
1017 }
1018 }
1019
1020 if self.state == OptimizerState::Optimizing {
1021 let recommendations = self.generate_recommendations()?;
1022
1023 if let Ok(mut active_recs) = self.active_recommendations.lock() {
1024 active_recs.extend(recommendations);
1025
1026 let auto_apply: Vec<_> = active_recs
1028 .iter()
1029 .enumerate()
1030 .filter(|(_, rec)| rec.risk_level == RiskLevel::Low && rec.confidence > 0.9)
1031 .map(|(i, _)| i)
1032 .collect();
1033
1034 for &index in auto_apply.iter().rev() {
1035 if let Some(rec) = active_recs.get(index).cloned() {
1036 if let Ok(mut params) = self.current_parameters.write() {
1037 if let Ok(value) = rec.suggested_value.parse::<f64>() {
1038 params.insert(rec.parameter.clone(), value);
1039 active_recs.remove(index);
1040 println!(
1041 "🤖 Auto-applied: {} = {}",
1042 rec.parameter, rec.suggested_value
1043 );
1044 }
1045 }
1046 }
1047 }
1048 }
1049 }
1050
1051 self.last_optimization = Instant::now();
1052 Ok(())
1053 }
1054
1055 fn has_sufficient_learning_data(&self) -> bool {
1057 if let Ok(history) = self.performance_history.lock() {
1058 history.values().any(|metrics| metrics.len() >= 10)
1059 } else {
1060 false
1061 }
1062 }
1063
1064 fn generate_recommendations(&self) -> CoreResult<Vec<OptimizationRecommendation>> {
1066 let mut recommendations = Vec::new();
1067
1068 if let Ok(history) = self.performance_history.lock() {
1070 for (workload, metrics) in history.iter() {
1071 if let Some(latest) = metrics.back() {
1072 if latest.name == "execution_time" && latest.trend == Trend::Degrading {
1074 recommendations.push(OptimizationRecommendation {
1075 parameter: "thread_count".to_string(),
1076 current_value: 4.to_string(),
1077 suggested_value: 8.to_string(),
1078 expected_impact: Impact {
1079 performance_improvement: 25.0,
1080 memory_change: 10.0,
1081 energy_change: 5.0,
1082 benefit_score: 0.8,
1083 },
1084 confidence: 0.85,
1085 rationale: format!("Workload '{workload}' shows degrading execution time. Increasing thread count may improve parallelization."),
1086 risk_level: RiskLevel::Low,
1087 });
1088 }
1089
1090 if latest.name == "memory_usage" && latest.value > 2000.0 {
1092 recommendations.push(OptimizationRecommendation {
1093 parameter: "chunk_size".to_string(),
1094 current_value: 1048576.to_string(),
1095 suggested_value: 524288.to_string(),
1096 expected_impact: Impact {
1097 performance_improvement: 5.0,
1098 memory_change: -30.0,
1099 energy_change: -10.0,
1100 benefit_score: 0.7,
1101 },
1102 confidence: 0.9,
1103 rationale: "High memory usage detected. Reducing chunk size may improve memory efficiency.".to_string(),
1104 risk_level: RiskLevel::Low,
1105 });
1106 }
1107 }
1108 }
1109 }
1110
1111 Ok(recommendations)
1112 }
1113}
1114
1115#[derive(Debug, Clone)]
1117pub struct OptimizerStatistics {
1118 pub state: OptimizerState,
1120 pub registered_workloads: usize,
1122 pub active_recommendations: usize,
1124 pub optimized_parameters: usize,
1126 pub last_optimization: Instant,
1128 pub uptime: Duration,
1130}
1131
1132#[cfg(test)]
1133mod tests {
1134 use super::*;
1135
1136 #[test]
1137 fn test_optimizer_creation() {
1138 let config = OptimizationConfig::production();
1139 let optimizer = AdaptiveOptimizer::new(config);
1140 assert!(optimizer.is_ok());
1141
1142 let optimizer = optimizer.expect("Operation failed");
1143 assert_eq!(optimizer.state, OptimizerState::Stopped);
1144 }
1145
1146 #[test]
1147 fn test_workload_profile_builder() {
1148 let workload = WorkloadProfile::builder()
1149 .with_name("test_workload")
1150 .with_data_size(1000000)
1151 .with_compute_intensity(0.8)
1152 .with_workload_type(WorkloadType::ComputeIntensive)
1153 .with_priority(Priority::High)
1154 .build();
1155
1156 assert_eq!(workload.name, "test_workload");
1157 assert_eq!(workload.data_size, 1000000);
1158 assert_eq!(workload.compute_intensity, 0.8);
1159 assert_eq!(workload.workload_type, WorkloadType::ComputeIntensive);
1160 assert_eq!(workload.priority, Priority::High);
1161 }
1162
1163 #[test]
1164 fn test_optimization_config() {
1165 let config = OptimizationConfig::production()
1166 .with_goal(OptimizationGoal::Performance)
1167 .with_learningrate(0.01)
1168 .with_confidence_threshold(0.95);
1169
1170 assert_eq!(config.goal, OptimizationGoal::Performance);
1171 assert_eq!(config.learningrate, 0.01);
1172 assert_eq!(config.confidence_threshold, 0.95);
1173 }
1174
1175 #[test]
1176 fn test_workload_optimization_hints() {
1177 let workload = WorkloadProfile::builder()
1178 .with_name("compute_workload")
1179 .with_workload_type(WorkloadType::ComputeIntensive)
1180 .with_parallelism(true, Some(8))
1181 .build();
1182
1183 let hints = workload.get_optimization_hints();
1184 assert!(hints
1185 .algorithm_preferences
1186 .contains(&AlgorithmPreference::Parallel));
1187 assert_eq!(hints.preferred_thread_count, Some(8));
1188 }
1189
1190 #[test]
1191 fn test_workload_registration() {
1192 let config = OptimizationConfig::default();
1193 let mut optimizer = AdaptiveOptimizer::new(config).expect("Operation failed");
1194
1195 let workload = WorkloadProfile::builder()
1196 .with_name("test_registration")
1197 .build();
1198
1199 let result = optimizer.register_workload(workload);
1200 assert!(result.is_ok());
1201
1202 let stats = optimizer.get_statistics();
1203 assert_eq!(stats.registered_workloads, 1);
1204 }
1205
1206 #[test]
1207 fn test_metric_recording() {
1208 let config = OptimizationConfig::default();
1209 let mut optimizer = AdaptiveOptimizer::new(config).expect("Operation failed");
1210
1211 let result = optimizer.record_metric("test_workload", "execution_time", 150.0);
1212 assert!(result.is_ok());
1213 }
1214
1215 #[test]
1216 fn test_trend_calculation() {
1217 let config = OptimizationConfig::default();
1218 let optimizer = AdaptiveOptimizer::new(config).expect("Operation failed");
1219
1220 let trend = optimizer.calculate_trend("test", "metric", 100.0);
1222 assert_eq!(trend, Trend::Unknown);
1223 }
1224
1225 #[test]
1226 fn test_resource_constraints() {
1227 let constraints = ResourceConstraints {
1228 max_memory_usage: Some(1024 * 1024 * 1024), max_cpu_usage: Some(0.8),
1230 max_threads: Some(16),
1231 ..Default::default()
1232 };
1233
1234 assert_eq!(constraints.max_memory_usage, Some(1024 * 1024 * 1024));
1235 assert_eq!(constraints.max_cpu_usage, Some(0.8));
1236 assert_eq!(constraints.max_threads, Some(16));
1237 }
1238
1239 #[test]
1240 fn test_optimization_goal_configuration() {
1241 let performance_config =
1242 OptimizationConfig::production().with_goal(OptimizationGoal::Performance);
1243 assert_eq!(performance_config.goal, OptimizationGoal::Performance);
1244
1245 let memory_config = OptimizationConfig::memory_optimized();
1246 assert_eq!(memory_config.goal, OptimizationGoal::MemoryEfficiency);
1247
1248 let dev_config = OptimizationConfig::development();
1249 assert_eq!(dev_config.goal, OptimizationGoal::Development);
1250 }
1251}