1use crate::error::{CoreError, CoreResult};
8use crate::performance::{OptimizationSettings, PerformanceProfile, WorkloadType};
9use std::collections::{HashMap, VecDeque};
10use std::sync::{Arc, Mutex, RwLock};
11use std::thread;
12use std::time::{Duration, Instant};
13
14static GLOBAL_RESOURCE_MANAGER: std::sync::OnceLock<Arc<ResourceManager>> =
16 std::sync::OnceLock::new();
17
18#[derive(Debug)]
20pub struct ResourceManager {
21 allocator: Arc<Mutex<AdaptiveAllocator>>,
22 tuner: Arc<RwLock<AutoTuner>>,
23 monitor: Arc<Mutex<ResourceMonitor>>,
24 policies: Arc<RwLock<ResourcePolicies>>,
25}
26
27impl ResourceManager {
28 pub fn new() -> CoreResult<Self> {
30 let performance_profile = PerformanceProfile::detect();
31
32 Ok(Self {
33 allocator: Arc::new(Mutex::new(AdaptiveAllocator::new(
34 performance_profile.clone(),
35 )?)),
36 tuner: Arc::new(RwLock::new(AutoTuner::new(performance_profile.clone())?)),
37 monitor: Arc::new(Mutex::new(ResourceMonitor::new()?)),
38 policies: Arc::new(RwLock::new(ResourcePolicies::default())),
39 })
40 }
41
42 pub fn global() -> CoreResult<Arc<Self>> {
44 Ok(GLOBAL_RESOURCE_MANAGER
45 .get_or_init(|| Arc::new(Self::new().unwrap()))
46 .clone())
47 }
48
49 pub fn start(&self) -> CoreResult<()> {
51 let monitor = self.monitor.clone();
53 let policies = self.policies.clone();
54 let tuner = self.tuner.clone();
55
56 thread::spawn(move || loop {
57 if let Err(e) = Self::monitoring_loop(&monitor, &policies, &tuner) {
58 eprintln!("Resource monitoring error: {e:?}");
59 }
60 thread::sleep(Duration::from_secs(10));
61 });
62
63 let tuner_clone = self.tuner.clone();
65 let monitor_clone = self.monitor.clone();
66
67 thread::spawn(move || loop {
68 if let Err(e) = Self::tuning_loop(&tuner_clone, &monitor_clone) {
69 eprintln!("Auto-tuning error: {e:?}");
70 }
71 thread::sleep(Duration::from_secs(30));
72 });
73
74 Ok(())
75 }
76
77 fn monitoring_loop(
78 monitor: &Arc<Mutex<ResourceMonitor>>,
79 policies: &Arc<RwLock<ResourcePolicies>>,
80 tuner: &Arc<RwLock<AutoTuner>>,
81 ) -> CoreResult<()> {
82 let mut monitor = monitor.lock().unwrap();
83 let metrics = monitor.collect_metrics()?;
84
85 let policies = policies.read().unwrap();
87 if let Some(action) = policies.check_violations(&metrics)? {
88 match action {
89 PolicyAction::ScaleUp => {
90 let mut tuner = tuner.write().unwrap();
91 (*tuner).increase_resources(&metrics)?;
92 }
93 PolicyAction::ScaleDown => {
94 let mut tuner = tuner.write().unwrap();
95 (*tuner).decrease_resources(&metrics)?;
96 }
97 PolicyAction::Optimize => {
98 let mut tuner = tuner.write().unwrap();
99 tuner.optimize_configuration(&metrics)?;
100 }
101 PolicyAction::Alert => {
102 monitor.trigger_alert(&metrics)?;
103 }
104 }
105 }
106
107 Ok(())
108 }
109
110 fn tuning_loop(
111 tuner: &Arc<RwLock<AutoTuner>>,
112 monitor: &Arc<Mutex<ResourceMonitor>>,
113 ) -> CoreResult<()> {
114 let metrics = {
115 let monitor = monitor.lock().unwrap();
116 monitor.get_current_metrics()?
117 };
118
119 let mut tuner = tuner.write().unwrap();
120 tuner.adaptive_optimization(&metrics)?;
121
122 Ok(())
123 }
124
125 pub fn allocate_optimized<T>(
127 &self,
128 size: usize,
129 workload_type: WorkloadType,
130 ) -> CoreResult<OptimizedAllocation<T>> {
131 let mut allocator = self.allocator.lock().unwrap();
132 allocator.allocate_optimized(size, workload_type)
133 }
134
135 pub fn get_utilization(&self) -> CoreResult<ResourceUtilization> {
137 let monitor = self.monitor.lock().unwrap();
138 monitor.get_current_utilization()
139 }
140
141 pub fn updatepolicies(&self, newpolicies: ResourcePolicies) -> CoreResult<()> {
143 let mut policies = self.policies.write().unwrap();
144 *policies = newpolicies;
145 Ok(())
146 }
147
148 pub fn get_recommendations(&self) -> CoreResult<Vec<TuningRecommendation>> {
150 let tuner = self.tuner.read().unwrap();
151 tuner.get_recommendations()
152 }
153}
154
155#[derive(Debug)]
157pub struct AdaptiveAllocator {
158 #[allow(dead_code)]
159 performance_profile: PerformanceProfile,
160 allocation_patterns: HashMap<WorkloadType, AllocationPattern>,
161 memory_pools: HashMap<String, MemoryPool>,
162 total_allocated: usize,
163 peak_allocated: usize,
164}
165
166#[derive(Debug, Clone)]
167struct AllocationPattern {
168 #[allow(dead_code)]
169 typical_size: usize,
170 #[allow(dead_code)]
171 typical_lifetime: Duration,
172 access_pattern: AccessPattern,
173 alignment_requirement: usize,
174}
175
176#[derive(Debug, Clone, Copy, PartialEq, Eq)]
177enum AccessPattern {
178 Sequential,
179 Random,
180 #[allow(dead_code)]
181 Strided,
182 Temporal,
183}
184
185impl AdaptiveAllocator {
186 pub fn new(performanceprofile: PerformanceProfile) -> CoreResult<Self> {
187 let mut allocator = Self {
188 performance_profile: performanceprofile,
189 allocation_patterns: HashMap::new(),
190 memory_pools: HashMap::new(),
191 total_allocated: 0,
192 peak_allocated: 0,
193 };
194
195 allocator.initialize_patterns()?;
197
198 Ok(allocator)
199 }
200
201 fn initialize_patterns(&mut self) -> CoreResult<()> {
202 self.allocation_patterns.insert(
204 WorkloadType::LinearAlgebra,
205 AllocationPattern {
206 typical_size: 1024 * 1024, typical_lifetime: Duration::from_secs(60),
208 access_pattern: AccessPattern::Sequential,
209 alignment_requirement: 64, },
211 );
212
213 self.allocation_patterns.insert(
215 WorkloadType::Statistics,
216 AllocationPattern {
217 typical_size: 64 * 1024, typical_lifetime: Duration::from_secs(30),
219 access_pattern: AccessPattern::Random,
220 alignment_requirement: 32,
221 },
222 );
223
224 self.allocation_patterns.insert(
226 WorkloadType::SignalProcessing,
227 AllocationPattern {
228 typical_size: 256 * 1024, typical_lifetime: Duration::from_secs(45),
230 access_pattern: AccessPattern::Temporal,
231 alignment_requirement: 64,
232 },
233 );
234
235 Ok(())
236 }
237
238 pub fn allocate_optimized<T>(
239 &mut self,
240 size: usize,
241 workload_type: WorkloadType,
242 ) -> CoreResult<OptimizedAllocation<T>> {
243 let pattern = self
244 .allocation_patterns
245 .get(&workload_type)
246 .cloned()
247 .unwrap_or_else(|| AllocationPattern {
248 typical_size: size,
249 typical_lifetime: Duration::from_secs(60),
250 access_pattern: AccessPattern::Sequential,
251 alignment_requirement: std::mem::align_of::<T>(),
252 });
253
254 let strategy = self.choose_allocation_strategy(size, &pattern)?;
256
257 let allocation = match strategy {
259 AllocationStrategy::Pool(pool_name) => self.allocate_from_pool(&pool_name, size)?,
260 AllocationStrategy::Direct => {
261 self.allocate_direct(size, pattern.alignment_requirement)?
262 }
263 AllocationStrategy::MemoryMapped => self.allocate_memory_mapped(size)?,
264 };
265
266 self.total_allocated += size * std::mem::size_of::<T>();
267 self.peak_allocated = self.peak_allocated.max(self.total_allocated);
268
269 Ok(allocation)
270 }
271
272 fn choose_allocation_strategy(
273 &self,
274 size: usize,
275 pattern: &AllocationPattern,
276 ) -> CoreResult<AllocationStrategy> {
277 let size_bytes = size * std::mem::size_of::<u8>();
278
279 if size_bytes > 100 * 1024 * 1024 {
281 return Ok(AllocationStrategy::MemoryMapped);
283 }
284
285 if size_bytes > 1024 && size_bytes < 10 * 1024 * 1024 {
287 let pool_name = format!("{}_{}", size_bytes / 1024, pattern.access_pattern as u8);
289 return Ok(AllocationStrategy::Pool(pool_name));
290 }
291
292 Ok(AllocationStrategy::Direct)
294 }
295
296 fn allocate_from_pool<T>(
297 &mut self,
298 pool_name: &str,
299 size: usize,
300 ) -> CoreResult<OptimizedAllocation<T>> {
301 if !self.memory_pools.contains_key(pool_name) {
303 let pool = MemoryPool::new(size * std::mem::size_of::<T>(), 10)?; self.memory_pools.insert(pool_name.to_string(), pool);
305 }
306
307 let pool = self.memory_pools.get_mut(pool_name).unwrap();
308 let ptr = pool.allocate(size * std::mem::size_of::<T>())?;
309
310 Ok(OptimizedAllocation {
311 ptr: ptr as *mut T,
312 size,
313 allocation_type: AllocationType::Pool(pool_name.to_string()),
314 alignment: 64,
315 })
316 }
317
318 fn allocate_direct<T>(
319 &self,
320 size: usize,
321 alignment: usize,
322 ) -> CoreResult<OptimizedAllocation<T>> {
323 let layout = std::alloc::Layout::from_size_align(
324 size * std::mem::size_of::<T>(),
325 alignment.max(std::mem::align_of::<T>()),
326 )
327 .map_err(|_| {
328 CoreError::AllocationError(crate::error::ErrorContext::new("Invalid layout"))
329 })?;
330
331 let ptr = unsafe { std::alloc::alloc(layout) as *mut T };
332 if ptr.is_null() {
333 return Err(CoreError::AllocationError(crate::error::ErrorContext::new(
334 "Allocation failed",
335 )));
336 }
337
338 Ok(OptimizedAllocation {
339 ptr,
340 size,
341 allocation_type: AllocationType::Direct(layout),
342 alignment,
343 })
344 }
345
346 fn allocate_memory_mapped<T>(&self, size: usize) -> CoreResult<OptimizedAllocation<T>> {
347 self.allocate_direct(size, 64)
350 }
351}
352
353#[derive(Debug)]
355pub struct OptimizedAllocation<T> {
356 ptr: *mut T,
357 size: usize,
358 allocation_type: AllocationType,
359 alignment: usize,
360}
361
362#[derive(Debug)]
363enum AllocationType {
364 Direct(std::alloc::Layout),
365 #[allow(dead_code)]
366 Pool(String),
367 #[allow(dead_code)]
368 MemoryMapped,
369}
370
371#[derive(Debug)]
372enum AllocationStrategy {
373 Direct,
374 Pool(String),
375 MemoryMapped,
376}
377
378impl<T> OptimizedAllocation<T> {
379 pub fn as_ptr(&self) -> *mut T {
381 self.ptr
382 }
383
384 pub fn size(&self) -> usize {
386 self.size
387 }
388
389 pub fn alignment(&self) -> usize {
391 self.alignment
392 }
393
394 pub fn is_cache_aligned(&self) -> bool {
396 self.alignment >= 64
397 }
398}
399
400impl<T> Drop for OptimizedAllocation<T> {
401 fn drop(&mut self) {
402 match &self.allocation_type {
403 AllocationType::Direct(layout) => unsafe {
404 std::alloc::dealloc(self.ptr as *mut u8, *layout);
405 },
406 AllocationType::Pool(_) => {
407 }
409 AllocationType::MemoryMapped => {
410 }
412 }
413 }
414}
415
416#[derive(Debug)]
418struct MemoryPool {
419 block_size: usize,
420 blocks: VecDeque<*mut u8>,
421 allocated_blocks: Vec<*mut u8>,
422}
423
424unsafe impl Send for MemoryPool {}
427unsafe impl Sync for MemoryPool {}
428
429impl MemoryPool {
430 fn new(block_size: usize, initial_blockcount: usize) -> CoreResult<Self> {
431 let mut pool = Self {
432 block_size,
433 blocks: VecDeque::new(),
434 allocated_blocks: Vec::new(),
435 };
436
437 for _ in 0..initial_blockcount {
439 pool.add_block()?;
440 }
441
442 Ok(pool)
443 }
444
445 fn add_block(&mut self) -> CoreResult<()> {
446 let layout = std::alloc::Layout::from_size_align(self.block_size, 64).map_err(|_| {
447 CoreError::AllocationError(crate::error::ErrorContext::new("Invalid layout"))
448 })?;
449
450 let ptr = unsafe { std::alloc::alloc(layout) };
451 if ptr.is_null() {
452 return Err(CoreError::AllocationError(crate::error::ErrorContext::new(
453 "Pool block allocation failed",
454 )));
455 }
456
457 self.blocks.push_back(ptr);
458 self.allocated_blocks.push(ptr);
459 Ok(())
460 }
461
462 fn allocate(&mut self, size: usize) -> CoreResult<*mut u8> {
463 if size > self.block_size {
464 return Err(CoreError::AllocationError(crate::error::ErrorContext::new(
465 "Requested size exceeds block size",
466 )));
467 }
468
469 if self.blocks.is_empty() {
470 self.add_block()?;
471 }
472
473 Ok(self.blocks.pop_front().unwrap())
474 }
475
476 #[allow(dead_code)]
477 fn deallocate(&mut self, ptr: *mut u8) {
478 self.blocks.push_back(ptr);
479 }
480}
481
482impl Drop for MemoryPool {
483 fn drop(&mut self) {
484 for &ptr in &self.allocated_blocks {
485 unsafe {
486 let layout = std::alloc::Layout::from_size_align(self.block_size, 64).unwrap();
487 std::alloc::dealloc(ptr, layout);
488 }
489 }
490 }
491}
492
493#[derive(Debug)]
495pub struct AutoTuner {
496 performance_profile: PerformanceProfile,
497 optimization_history: VecDeque<OptimizationEvent>,
498 current_settings: OptimizationSettings,
499 #[allow(dead_code)]
500 learningrate: f64,
501 #[allow(dead_code)]
502 stability_threshold: f64,
503}
504
505#[derive(Debug, Clone)]
506struct OptimizationEvent {
507 #[allow(dead_code)]
508 timestamp: Instant,
509 #[allow(dead_code)]
510 metrics_before: ResourceMetrics,
511 #[allow(dead_code)]
512 metrics_after: ResourceMetrics,
513 #[allow(dead_code)]
514 settings_applied: OptimizationSettings,
515 performance_delta: f64,
516}
517
518#[allow(dead_code)]
519impl AutoTuner {
520 pub fn new(performanceprofile: PerformanceProfile) -> CoreResult<Self> {
521 Ok(Self {
522 performance_profile: performanceprofile,
523 optimization_history: VecDeque::with_capacity(100usize),
524 current_settings: OptimizationSettings::default(),
525 learningrate: 0.1f64,
526 stability_threshold: 0.05f64, })
528 }
529
530 pub fn adaptive_optimization(&mut self, metrics: &ResourceMetrics) -> CoreResult<()> {
531 let performance_score = self.calculate_performance_score(metrics);
533
534 if self.needs_optimization(metrics, performance_score) {
536 let new_settings = self.generate_optimized_settings(metrics)?;
537 self.apply_settings(&new_settings)?;
538
539 let event = OptimizationEvent {
541 timestamp: Instant::now(),
542 metrics_before: metrics.clone(),
543 metrics_after: metrics.clone(), settings_applied: new_settings.clone(),
545 performance_delta: 0.0f64, };
547
548 self.optimization_history.push_back(event);
549 self.current_settings = new_settings;
550 }
551
552 Ok(())
553 }
554
555 fn calculate_performance_score(&self, metrics: &ResourceMetrics) -> f64 {
556 let cpu_efficiency = 1.0 - metrics.cpu_utilization;
557 let memory_efficiency = 1.0 - metrics.memory_utilization;
558 let throughput_score = metrics.operations_per_second / 1000.0f64; (cpu_efficiency + memory_efficiency + throughput_score) / 3.0
561 }
562
563 fn needs_retuning(&self, performancescore: f64, metrics: &ResourceMetrics) -> bool {
564 if performancescore < 0.7 {
566 return true;
568 }
569
570 if metrics.cpu_utilization > 0.9 || metrics.memory_utilization > 0.9 {
572 return true;
573 }
574
575 if metrics.cache_miss_rate > 0.1 {
577 return true;
579 }
580
581 false
582 }
583
584 fn generate_optimized_settings(
585 &self,
586 metrics: &ResourceMetrics,
587 ) -> CoreResult<OptimizationSettings> {
588 let mut settings = self.current_settings.clone();
589
590 if metrics.cpu_utilization > 0.9 {
592 settings.num_threads = ((settings.num_threads as f64) * 0.8f64) as usize;
594 } else if metrics.cpu_utilization < 0.5 {
595 settings.num_threads = ((settings.num_threads as f64) * 1.2f64) as usize;
597 }
598
599 if metrics.memory_utilization > 0.9 {
601 settings.chunk_size = ((settings.chunk_size as f64) * 0.8f64) as usize;
603 }
604
605 if metrics.cache_miss_rate > 0.1 {
607 settings.prefetch_enabled = true;
609 settings.block_size = ((settings.block_size as f64) * 0.8f64) as usize;
610 }
611
612 Ok(settings)
613 }
614
615 fn apply_settings(&self, settings: &OptimizationSettings) -> CoreResult<()> {
616 let _ = settings.num_threads; Ok(())
623 }
624
625 pub fn metrics(&mut self, metrics: &ResourceMetrics) -> CoreResult<()> {
626 self.current_settings.num_threads =
627 ((self.current_settings.num_threads as f64) * 1.2f64) as usize;
628 self.current_settings.chunk_size =
629 ((self.current_settings.chunk_size as f64) * 1.1f64) as usize;
630 self.apply_settings(&self.current_settings)
631 }
632
633 pub fn metrics_2(&mut self, metrics: &ResourceMetrics) -> CoreResult<()> {
634 self.current_settings.num_threads =
635 ((self.current_settings.num_threads as f64) * 0.8f64) as usize;
636 self.current_settings.chunk_size =
637 ((self.current_settings.chunk_size as f64) * 0.9f64) as usize;
638 self.apply_settings(&self.current_settings)
639 }
640
641 pub fn optimize_configuration(&mut self, metrics: &ResourceMetrics) -> CoreResult<()> {
642 let optimized_settings = self.generate_optimized_settings(metrics)?;
643 self.apply_settings(&optimized_settings)?;
644 self.current_settings = optimized_settings;
645 Ok(())
646 }
647
648 pub fn get_recommendations(&self) -> CoreResult<Vec<TuningRecommendation>> {
649 let mut recommendations = Vec::new();
650
651 if self.optimization_history.len() >= 5 {
653 let recent_events: Vec<_> = self.optimization_history.iter().rev().take(5).collect();
654
655 if recent_events.iter().all(|e| e.performance_delta < 0.0f64) {
657 recommendations.push(TuningRecommendation {
658 category: RecommendationCategory::Performance,
659 title: "Recent optimizations showing negative returns".to_string(),
660 description: "Consider reverting to previous stable configuration".to_string(),
661 priority: RecommendationPriority::High,
662 estimated_impact: ImpactLevel::Medium,
663 });
664 }
665 }
666
667 if self.current_settings.num_threads > self.performance_profile.cpu_cores * 2 {
669 recommendations.push(TuningRecommendation {
670 category: RecommendationCategory::Resource,
671 title: "Thread count exceeds optimal range".to_string(),
672 description: format!(
673 "Current threads: {}, optimal range: 1-{}",
674 self.current_settings.num_threads,
675 self.performance_profile.cpu_cores * 2
676 ),
677 priority: RecommendationPriority::Medium,
678 estimated_impact: ImpactLevel::Low,
679 });
680 }
681
682 Ok(recommendations)
683 }
684
685 pub fn increase_resources(&mut self, metrics: &ResourceMetrics) -> CoreResult<()> {
686 Ok(())
689 }
690
691 pub fn decrease_resources(&mut self, metrics: &ResourceMetrics) -> CoreResult<()> {
692 Ok(())
695 }
696
697 fn needs_optimization(&mut self, _metrics: &ResourceMetrics, _performancescore: f64) -> bool {
698 false
701 }
702}
703
704impl Default for OptimizationSettings {
705 fn default() -> Self {
706 Self {
707 use_simd: true,
708 simd_instruction_set: crate::performance::SimdInstructionSet::Scalar,
709 chunk_size: 1024,
710 block_size: 64,
711 prefetch_enabled: false,
712 parallel_threshold: 10000,
713 num_threads: std::thread::available_parallelism()
714 .map(|n| n.get())
715 .unwrap_or(1),
716 }
717 }
718}
719
720#[derive(Debug)]
722pub struct ResourceMonitor {
723 metrics_history: VecDeque<ResourceMetrics>,
724 alert_thresholds: AlertThresholds,
725 last_collection: Instant,
726}
727
728#[derive(Debug, Clone)]
729pub struct ResourceMetrics {
730 pub timestamp: Instant,
731 pub cpu_utilization: f64,
732 pub memory_utilization: f64,
733 pub cache_miss_rate: f64,
734 pub operations_per_second: f64,
735 pub memorybandwidth_usage: f64,
736 pub thread_contention: f64,
737}
738
739#[derive(Debug, Clone)]
740struct AlertThresholds {
741 cpu_warning: f64,
742 cpu_critical: f64,
743 memory_warning: f64,
744 memory_critical: f64,
745 cache_miss_warning: f64,
746 cache_miss_critical: f64,
747}
748
749#[derive(Debug, Clone)]
750pub enum AlertSeverity {
751 Info,
752 Warning,
753 Critical,
754}
755
756#[derive(Debug, Clone)]
757pub struct AlertMessage {
758 pub severity: AlertSeverity,
759 pub resource: String,
760 pub message: String,
761 pub timestamp: Instant,
762 pub suggested_action: String,
763}
764
765impl Default for AlertThresholds {
766 fn default() -> Self {
767 Self {
768 cpu_warning: 0.8f64,
769 cpu_critical: 0.95f64,
770 memory_warning: 0.8f64,
771 memory_critical: 0.95f64,
772 cache_miss_warning: 0.1f64,
773 cache_miss_critical: 0.2f64,
774 }
775 }
776}
777
778impl ResourceMonitor {
779 pub fn new() -> CoreResult<Self> {
780 Ok(Self {
781 metrics_history: VecDeque::with_capacity(1000usize),
782 alert_thresholds: AlertThresholds::default(),
783 last_collection: Instant::now(),
784 })
785 }
786
787 pub fn collect_metrics(&mut self) -> CoreResult<ResourceMetrics> {
788 let metrics = ResourceMetrics {
789 timestamp: Instant::now(),
790 cpu_utilization: self.get_cpu_utilization()?,
791 memory_utilization: self.get_memory_utilization()?,
792 cache_miss_rate: self.get_cache_miss_rate()?,
793 operations_per_second: self.get_operations_per_second()?,
794 memorybandwidth_usage: self.get_memorybandwidth_usage()?,
795 thread_contention: self.get_thread_contention()?,
796 };
797
798 self.metrics_history.push_back(metrics.clone());
799
800 while self.metrics_history.len() > 1000 {
802 self.metrics_history.pop_front();
803 }
804
805 self.last_collection = Instant::now();
806 Ok(metrics)
807 }
808
809 fn get_cpu_utilization(&self) -> CoreResult<f64> {
810 #[cfg(target_os = "linux")]
811 {
812 self.get_cpu_utilization_linux()
813 }
814 #[cfg(target_os = "windows")]
815 {
816 Ok(0.5) }
819 #[cfg(target_os = "macos")]
820 {
821 Ok(0.5) }
824 #[cfg(not(any(target_os = "linux", target_os = "windows", target_os = "macos")))]
825 {
826 Ok(0.5) }
828 }
829
830 #[cfg(target_os = "linux")]
831 fn get_cpu_utilization_linux(&self) -> CoreResult<f64> {
832 if let Ok(stat_content) = std::fs::read_to_string("/proc/stat") {
834 if let Some(cpu_line) = stat_content.lines().next() {
835 let fields: Vec<&str> = cpu_line.split_whitespace().collect();
836 if fields.len() >= 8 && fields[0usize] == "cpu" {
837 let user: u64 = fields[1usize].parse().unwrap_or(0);
838 let nice: u64 = fields[2usize].parse().unwrap_or(0);
839 let system: u64 = fields[3usize].parse().unwrap_or(0);
840 let idle: u64 = fields[4usize].parse().unwrap_or(0);
841 let iowait: u64 = fields[5usize].parse().unwrap_or(0);
842 let irq: u64 = fields[6usize].parse().unwrap_or(0);
843 let softirq: u64 = fields[7usize].parse().unwrap_or(0);
844
845 let total_idle = idle + iowait;
846 let total_active = user + nice + system + irq + softirq;
847 let total = total_idle + total_active;
848
849 if total > 0 {
850 return Ok(total_active as f64 / total as f64);
851 }
852 }
853 }
854 }
855
856 if let Ok(loadavg) = std::fs::read_to_string("/proc/loadavg") {
858 if let Some(load_str) = loadavg.split_whitespace().next() {
859 if let Ok(load) = load_str.parse::<f64>() {
860 let cpu_cores = std::thread::available_parallelism()
861 .map(|n| n.get())
862 .unwrap_or(1) as f64;
863 return Ok((load / cpu_cores).min(1.0));
864 }
865 }
866 }
867
868 Ok(0.5) }
870
871 fn get_memory_utilization(&self) -> CoreResult<f64> {
872 #[cfg(target_os = "linux")]
873 {
874 self.get_memory_utilization_linux()
875 }
876 #[cfg(target_os = "windows")]
877 {
878 Ok(0.6) }
881 #[cfg(target_os = "macos")]
882 {
883 Ok(0.6) }
886 #[cfg(not(any(target_os = "linux", target_os = "windows", target_os = "macos")))]
887 {
888 Ok(0.6) }
890 }
891
892 #[cfg(target_os = "linux")]
893 fn get_memory_utilization_linux(&self) -> CoreResult<f64> {
894 if let Ok(meminfo) = std::fs::read_to_string("/proc/meminfo") {
896 let mut mem_total = 0u64;
897 let mut mem_available = 0u64;
898 let mut mem_free = 0u64;
899 let mut mem_buffers = 0u64;
900 let mut mem_cached = 0u64;
901
902 for line in meminfo.lines() {
903 let parts: Vec<&str> = line.split_whitespace().collect();
904 if parts.len() >= 2 {
905 if let Ok(value) = parts[1usize].parse::<u64>() {
906 match parts[0usize] {
907 "MemTotal:" => mem_total = value,
908 "MemAvailable:" => mem_available = value,
909 "MemFree:" => mem_free = value,
910 "Buffers:" => mem_buffers = value,
911 "Cached:" => mem_cached = value,
912 _ => {}
913 }
914 }
915 }
916 }
917
918 if mem_total > 0 {
919 if mem_available > 0 {
921 let used = mem_total - mem_available;
922 return Ok(used as f64 / mem_total as f64);
923 } else {
924 let used = mem_total.saturating_sub(mem_free + mem_buffers + mem_cached);
926 return Ok(used as f64 / mem_total as f64);
927 }
928 }
929 }
930
931 Ok(0.6) }
933
934 fn get_cache_miss_rate(&self) -> CoreResult<f64> {
935 #[cfg(target_os = "linux")]
937 {
938 if let Ok(stat) = std::fs::read_to_string("/proc/stat") {
940 for line in stat.lines() {
942 if line.starts_with("cache") {
943 let parts: Vec<&str> = line.split_whitespace().collect();
944 if parts.len() >= 3 {
945 if let (Ok(misses), Ok(hits)) =
946 (parts[1usize].parse::<f64>(), parts[2usize].parse::<f64>())
947 {
948 let total = misses + hits;
949 if total > 0.0 {
950 return Ok(misses / total);
951 }
952 }
953 }
954 }
955 }
956 }
957 }
958
959 #[cfg(target_os = "macos")]
960 {
961 use std::process::Command;
963 if let Ok(output) = Command::new("sysctl")
964 .args(["hw.cacheconfig", "hw.cachesize"])
965 .output()
966 {
967 if output.status.success() {
968 return Ok(0.03); }
972 }
973 }
974
975 #[cfg(target_os = "windows")]
976 {
977 return Ok(0.04); }
982
983 #[cfg(not(target_os = "windows"))]
984 {
985 let recent_metrics: Vec<_> = self.metrics_history.iter().rev().take(10).collect();
987 if recent_metrics.len() > 5 {
988 let avg_cpu = recent_metrics
989 .iter()
990 .map(|m| m.cpu_utilization)
991 .sum::<f64>()
992 / recent_metrics.len() as f64;
993 let avg_memory = recent_metrics
994 .iter()
995 .map(|m| m.memory_utilization)
996 .sum::<f64>()
997 / recent_metrics.len() as f64;
998
999 let estimated_miss_rate = 0.02 + (avg_cpu + avg_memory) * 0.05f64;
1001 Ok(estimated_miss_rate.min(0.15)) } else {
1003 Ok(0.05) }
1005 }
1006 }
1007
1008 fn get_operations_per_second(&self) -> CoreResult<f64> {
1009 let recent_metrics: Vec<_> = self.metrics_history.iter().rev().take(5).collect();
1011
1012 if recent_metrics.len() >= 2 {
1013 let mut total_ops = 0.0f64;
1015 let mut total_time = 0.0f64;
1016
1017 for (i, metrics) in recent_metrics.iter().enumerate() {
1018 if i > 0 {
1019 let prev_metrics = recent_metrics[0usize.saturating_sub(1)];
1020 let time_diff = metrics
1021 .timestamp
1022 .duration_since(prev_metrics.timestamp)
1023 .as_secs_f64();
1024
1025 if time_diff > 0.0 {
1026 let cpu_factor = metrics.cpu_utilization;
1028 let memory_factor = 1.0 - metrics.memory_utilization; let cache_factor = 1.0 - metrics.cache_miss_rate; let estimated_ops = 1000.0 * cpu_factor * memory_factor * cache_factor;
1033 total_ops += estimated_ops * time_diff;
1034 total_time += time_diff;
1035 }
1036 }
1037 }
1038
1039 if total_time > 0.0 {
1040 let ops_per_second = total_ops / total_time;
1041 return Ok(ops_per_second.clamp(100.0, 50000.0f64));
1043 }
1044 }
1045
1046 let current_cpu = self
1048 .metrics_history
1049 .back()
1050 .map(|m| m.cpu_utilization)
1051 .unwrap_or(0.5);
1052 let current_memory = self
1053 .metrics_history
1054 .back()
1055 .map(|m| m.memory_utilization)
1056 .unwrap_or(0.5);
1057
1058 let base_ops = 2000.0f64;
1060 let load_factor = (2.0 - current_cpu - current_memory).max(0.1);
1061 Ok(base_ops * load_factor)
1062 }
1063
1064 fn get_memorybandwidth_usage(&self) -> CoreResult<f64> {
1065 #[cfg(target_os = "linux")]
1067 {
1068 if let (Ok(meminfo), Ok(vmstat)) = (
1070 std::fs::read_to_string("/proc/meminfo"),
1071 std::fs::read_to_string("/proc/vmstat"),
1072 ) {
1073 let mut total_memory = 0u64;
1074 let mut available_memory = 0u64;
1075 let mut page_faults = 0u64;
1076
1077 for line in meminfo.lines() {
1079 if line.starts_with("MemTotal:") {
1080 if let Some(value) = line.split_whitespace().nth(1) {
1081 total_memory = value.parse().unwrap_or(0);
1082 }
1083 } else if line.starts_with("MemAvailable:") {
1084 if let Some(value) = line.split_whitespace().nth(1) {
1085 available_memory = value.parse().unwrap_or(0);
1086 }
1087 }
1088 }
1089
1090 for line in vmstat.lines() {
1092 if line.starts_with("pgfault ") {
1093 if let Some(value) = line.split_whitespace().nth(1) {
1094 page_faults = value.parse().unwrap_or(0);
1095 }
1096 }
1097 }
1098
1099 if total_memory > 0 {
1100 let memory_usage = 1.0 - (available_memory as f64 / total_memory as f64);
1101 let bandwidth_estimate =
1103 memory_usage * 0.7 + (page_faults as f64 / 1000000.0f64).min(0.3);
1104 return Ok(bandwidth_estimate.min(1.0));
1105 }
1106 }
1107 }
1108
1109 #[cfg(target_os = "macos")]
1110 {
1111 use std::process::Command;
1113 if let Ok(output) = Command::new("vm_stat").output() {
1114 if output.status.success() {
1115 let output_str = String::from_utf8_lossy(&output.stdout);
1116 let mut pages_free = 0u64;
1117 let mut pages_active = 0u64;
1118 let mut pages_inactive = 0u64;
1119
1120 for line in output_str.lines() {
1121 if line.contains("Pages free:") {
1122 if let Some(value) = line.split(':').nth(1) {
1123 pages_free = value.trim().replace(".", "").parse().unwrap_or(0);
1124 }
1125 } else if line.contains("Pages active:") {
1126 if let Some(value) = line.split(':').nth(1) {
1127 pages_active = value.trim().replace(".", "").parse().unwrap_or(0);
1128 }
1129 } else if line.contains("Pages inactive:") {
1130 if let Some(value) = line.split(':').nth(1) {
1131 pages_inactive = value.trim().replace(".", "").parse().unwrap_or(0);
1132 }
1133 }
1134 }
1135
1136 let total_pages = pages_free + pages_active + pages_inactive;
1137 if total_pages > 0 {
1138 let memory_pressure =
1139 (pages_active + pages_inactive) as f64 / total_pages as f64;
1140 return Ok((memory_pressure * 0.8f64).min(1.0));
1141 }
1142 }
1143 }
1144 }
1145
1146 #[cfg(target_os = "windows")]
1147 {
1148 let recent_memory_usage = self
1152 .metrics_history
1153 .iter()
1154 .rev()
1155 .take(3)
1156 .map(|m| m.memory_utilization)
1157 .sum::<f64>()
1158 / 3.0f64;
1159 return Ok((recent_memory_usage * 0.6f64).min(1.0));
1160 }
1161
1162 #[cfg(not(target_os = "windows"))]
1163 {
1164 let recent_metrics: Vec<_> = self.metrics_history.iter().rev().take(10).collect();
1166 if recent_metrics.len() >= 3 {
1167 let avg_memory_usage = recent_metrics
1168 .iter()
1169 .map(|m| m.memory_utilization)
1170 .sum::<f64>()
1171 / recent_metrics.len() as f64;
1172 let memory_variance = recent_metrics
1173 .iter()
1174 .map(|m| (m.memory_utilization - avg_memory_usage).powi(2))
1175 .sum::<f64>()
1176 / recent_metrics.len() as f64;
1177
1178 let bandwidth_usage = avg_memory_usage * 0.6 + memory_variance * 10.0f64;
1180 Ok(bandwidth_usage.min(0.95))
1181 } else {
1182 Ok(0.3) }
1184 }
1185 }
1186
1187 fn get_thread_contention(&self) -> CoreResult<f64> {
1188 #[cfg(target_os = "linux")]
1190 {
1191 if let (Ok(stat), Ok(loadavg)) = (
1193 std::fs::read_to_string("/proc/stat"),
1194 std::fs::read_to_string("/proc/loadavg"),
1195 ) {
1196 let load_parts: Vec<&str> = loadavg.split_whitespace().collect();
1198 if load_parts.len() >= 3 {
1199 if let Ok(load_1min) = load_parts[0usize].parse::<f64>() {
1200 #[cfg(feature = "parallel")]
1202 let cpu_count = num_cpus::get() as f64;
1203 #[cfg(not(feature = "parallel"))]
1204 let cpu_count = std::thread::available_parallelism()
1205 .map(|n| n.get() as f64)
1206 .unwrap_or(4.0);
1207
1208 let contention = if load_1min > cpu_count {
1210 ((load_1min - cpu_count) / cpu_count).min(1.0)
1211 } else {
1212 0.0
1213 };
1214
1215 for line in stat.lines() {
1217 if line.starts_with("ctxt ") {
1218 if let Some(value_str) = line.split_whitespace().nth(1) {
1219 if let Ok(context_switches) = value_str.parse::<u64>() {
1220 let cs_factor =
1222 (context_switches as f64 / 1000000.0f64).min(0.3);
1223 return Ok((contention + cs_factor).min(1.0));
1224 }
1225 }
1226 }
1227 }
1228
1229 return Ok(contention);
1230 }
1231 }
1232 }
1233 }
1234
1235 #[cfg(target_os = "macos")]
1236 {
1237 use std::process::Command;
1239 if let Ok(output) = Command::new("uptime").output() {
1240 if output.status.success() {
1241 let output_str = String::from_utf8_lossy(&output.stdout);
1242 if let Some(load_section) = output_str.split("load averages: ").nth(1) {
1244 let load_parts: Vec<&str> = load_section.split_whitespace().collect();
1245 if !load_parts.is_empty() {
1246 if let Ok(load_1min) = load_parts[0usize].parse::<f64>() {
1247 #[cfg(feature = "parallel")]
1248 let cpu_count = num_cpus::get() as f64;
1249 #[cfg(not(feature = "parallel"))]
1250 let cpu_count = std::thread::available_parallelism()
1251 .map(|n| n.get() as f64)
1252 .unwrap_or(4.0);
1253 let contention = if load_1min > cpu_count {
1254 ((load_1min - cpu_count) / cpu_count).min(1.0)
1255 } else {
1256 0.0
1257 };
1258 return Ok(contention);
1259 }
1260 }
1261 }
1262 }
1263 }
1264 }
1265
1266 #[cfg(target_os = "windows")]
1267 {
1268 let recent_cpu_usage = self
1272 .metrics_history
1273 .iter()
1274 .rev()
1275 .take(5)
1276 .map(|m| m.cpu_utilization)
1277 .sum::<f64>()
1278 / 5.0f64;
1279
1280 let contention_estimate = if recent_cpu_usage > 0.8 {
1282 (recent_cpu_usage - 0.8f64) * 2.0
1283 } else {
1284 0.0
1285 };
1286 return Ok(contention_estimate.min(0.5));
1287 }
1288
1289 #[cfg(not(target_os = "windows"))]
1290 {
1291 let recent_metrics: Vec<_> = self.metrics_history.iter().rev().take(10).collect();
1293 if recent_metrics.len() >= 5 {
1294 let avg_cpu = recent_metrics
1295 .iter()
1296 .map(|m| m.cpu_utilization)
1297 .sum::<f64>()
1298 / recent_metrics.len() as f64;
1299 let cpu_variance = recent_metrics
1300 .iter()
1301 .map(|m| (m.cpu_utilization - avg_cpu).powi(2))
1302 .sum::<f64>()
1303 / recent_metrics.len() as f64;
1304
1305 let contention_score = if avg_cpu > 0.7 {
1307 let base_contention = (avg_cpu - 0.7f64) / 0.3f64; let variance_factor = (cpu_variance * 20.0f64).min(0.3); (base_contention + variance_factor).min(1.0)
1310 } else {
1311 (cpu_variance * 5.0f64).min(0.2) };
1313
1314 Ok(contention_score)
1315 } else {
1316 Ok(0.1) }
1318 }
1319 }
1320
1321 pub fn get_current_metrics(&self) -> CoreResult<ResourceMetrics> {
1322 use crate::error::ErrorContext;
1323 self.metrics_history.back().cloned().ok_or_else(|| {
1324 CoreError::InvalidState(ErrorContext {
1325 message: "No metrics collected yet".to_string(),
1326 location: None,
1327 cause: None,
1328 })
1329 })
1330 }
1331
1332 pub fn get_current_utilization(&self) -> CoreResult<ResourceUtilization> {
1333 let metrics = self.get_current_metrics()?;
1334 Ok(ResourceUtilization {
1335 cpu_percent: metrics.cpu_utilization * 100.0f64,
1336 memory_percent: metrics.memory_utilization * 100.0f64,
1337 cache_efficiency: (1.0 - metrics.cache_miss_rate) * 100.0f64,
1338 throughput_ops_per_sec: metrics.operations_per_second,
1339 memorybandwidth_percent: metrics.memorybandwidth_usage * 100.0f64,
1340 })
1341 }
1342
1343 pub fn trigger_alert(&self, metrics: &ResourceMetrics) -> CoreResult<()> {
1344 let thresholds = &self.alert_thresholds;
1346 let mut alerts = Vec::new();
1347
1348 if metrics.cpu_utilization >= thresholds.cpu_critical {
1350 alerts.push(AlertMessage {
1351 severity: AlertSeverity::Critical,
1352 resource: "CPU".to_string(),
1353 message: format!(
1354 "Critical CPU utilization: {:.1}% (threshold: {:.1}%)",
1355 metrics.cpu_utilization * 100.0f64,
1356 thresholds.cpu_critical * 100.0f64
1357 ),
1358 timestamp: metrics.timestamp,
1359 suggested_action: "Consider scaling up resources or optimizing workload"
1360 .to_string(),
1361 });
1362 } else if metrics.cpu_utilization >= thresholds.cpu_warning {
1363 alerts.push(AlertMessage {
1364 severity: AlertSeverity::Warning,
1365 resource: "CPU".to_string(),
1366 message: format!(
1367 "High CPU utilization: {:.1}% (threshold: {:.1}%)",
1368 metrics.cpu_utilization * 100.0f64,
1369 thresholds.cpu_warning * 100.0f64
1370 ),
1371 timestamp: metrics.timestamp,
1372 suggested_action: "Monitor closely and prepare to scale if trend continues"
1373 .to_string(),
1374 });
1375 }
1376
1377 if metrics.memory_utilization >= thresholds.memory_critical {
1379 alerts.push(AlertMessage {
1380 severity: AlertSeverity::Critical,
1381 resource: "Memory".to_string(),
1382 message: format!(
1383 "Critical memory utilization: {:.1}% (threshold: {:.1}%)",
1384 metrics.memory_utilization * 100.0f64,
1385 thresholds.memory_critical * 100.0f64
1386 ),
1387 timestamp: metrics.timestamp,
1388 suggested_action: "Immediate memory optimization or resource scaling required"
1389 .to_string(),
1390 });
1391 } else if metrics.memory_utilization >= thresholds.memory_warning {
1392 alerts.push(AlertMessage {
1393 severity: AlertSeverity::Warning,
1394 resource: "Memory".to_string(),
1395 message: format!(
1396 "High memory utilization: {:.1}% (threshold: {:.1}%)",
1397 metrics.memory_utilization * 100.0f64,
1398 thresholds.memory_warning * 100.0f64
1399 ),
1400 timestamp: metrics.timestamp,
1401 suggested_action: "Review memory usage patterns and optimize if possible"
1402 .to_string(),
1403 });
1404 }
1405
1406 if metrics.cache_miss_rate >= thresholds.cache_miss_critical {
1408 alerts.push(AlertMessage {
1409 severity: AlertSeverity::Critical,
1410 resource: "Cache".to_string(),
1411 message: format!("Critical cache miss rate: {:.1}% (threshold: {:.1}%)",
1412 metrics.cache_miss_rate * 100.0f64, thresholds.cache_miss_critical * 100.0f64),
1413 timestamp: metrics.timestamp,
1414 suggested_action: "Optimize data access patterns and consider memory hierarchy tuning".to_string(),
1415 });
1416 } else if metrics.cache_miss_rate >= thresholds.cache_miss_warning {
1417 alerts.push(AlertMessage {
1418 severity: AlertSeverity::Warning,
1419 resource: "Cache".to_string(),
1420 message: format!(
1421 "High cache miss rate: {:.1}% (threshold: {:.1}%)",
1422 metrics.cache_miss_rate * 100.0f64,
1423 thresholds.cache_miss_warning * 100.0f64
1424 ),
1425 timestamp: metrics.timestamp,
1426 suggested_action: "Review data locality and access patterns".to_string(),
1427 });
1428 }
1429
1430 if metrics.thread_contention >= 0.5 {
1432 alerts.push(AlertMessage {
1433 severity: AlertSeverity::Critical,
1434 resource: "Threading".to_string(),
1435 message: format!(
1436 "High thread contention: {:.1}%",
1437 metrics.thread_contention * 100.0f64
1438 ),
1439 timestamp: metrics.timestamp,
1440 suggested_action: "Reduce parallelism or optimize synchronization".to_string(),
1441 });
1442 } else if metrics.thread_contention >= 0.3 {
1443 alerts.push(AlertMessage {
1444 severity: AlertSeverity::Warning,
1445 resource: "Threading".to_string(),
1446 message: format!(
1447 "Moderate thread contention: {:.1}%",
1448 metrics.thread_contention * 100.0f64
1449 ),
1450 timestamp: metrics.timestamp,
1451 suggested_action: "Monitor threading patterns and consider optimization"
1452 .to_string(),
1453 });
1454 }
1455
1456 for alert in alerts {
1458 self.process_alert(&alert)?;
1459 }
1460
1461 Ok(())
1462 }
1463
1464 fn process_alert(&self, alert: &AlertMessage) -> CoreResult<()> {
1465 match alert.severity {
1467 AlertSeverity::Critical => {
1468 eprintln!(
1469 "đ¨ CRITICAL ALERT [{}] {}: {}",
1470 alert.resource, alert.message, alert.suggested_action
1471 );
1472 }
1473 AlertSeverity::Warning => {
1474 println!(
1475 "â ī¸ WARNING [{}] {}: {}",
1476 alert.resource, alert.message, alert.suggested_action
1477 );
1478 }
1479 AlertSeverity::Info => {
1480 println!(
1481 "âšī¸ INFO [{}] {}: {}",
1482 alert.resource, alert.message, alert.suggested_action
1483 );
1484 }
1485 }
1486
1487 if matches!(alert.severity, AlertSeverity::Critical) {
1495 self.attempt_automatic_remediation(alert)?;
1497 }
1498
1499 Ok(())
1500 }
1501
1502 fn attempt_automatic_remediation(&self, alert: &AlertMessage) -> CoreResult<()> {
1503 match alert.resource.as_str() {
1504 "CPU" => {
1505 println!("đ§ Auto-remediation: Reducing CPU-intensive operations");
1507 }
1508 "Memory" => {
1509 println!("đ§ Auto-remediation: Initiating memory cleanup");
1511 }
1512 "Cache" => {
1513 println!("đ§ Auto-remediation: Optimizing cache configuration");
1515 }
1516 "Threading" => {
1517 println!("đ§ Auto-remediation: Adjusting threading configuration");
1519 }
1520 _ => {}
1521 }
1522
1523 Ok(())
1524 }
1525}
1526
1527#[derive(Debug, Clone)]
1529pub struct ResourceUtilization {
1530 pub cpu_percent: f64,
1531 pub memory_percent: f64,
1532 pub cache_efficiency: f64,
1533 pub throughput_ops_per_sec: f64,
1534 pub memorybandwidth_percent: f64,
1535}
1536
1537#[derive(Debug, Clone)]
1539pub struct ResourcePolicies {
1540 pub max_cpu_utilization: f64,
1541 pub max_memory_utilization: f64,
1542 pub min_cache_efficiency: f64,
1543 pub auto_scaling_enabled: bool,
1544 pub performance_mode: PerformanceMode,
1545}
1546
1547#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1548pub enum PerformanceMode {
1549 Conservative, Balanced, Aggressive, }
1553
1554impl Default for ResourcePolicies {
1555 fn default() -> Self {
1556 Self {
1557 max_cpu_utilization: 0.8f64,
1558 max_memory_utilization: 0.8f64,
1559 min_cache_efficiency: 0.9f64,
1560 auto_scaling_enabled: true,
1561 performance_mode: PerformanceMode::Balanced,
1562 }
1563 }
1564}
1565
1566impl ResourcePolicies {
1567 pub fn check_violations(&self, metrics: &ResourceMetrics) -> CoreResult<Option<PolicyAction>> {
1568 if metrics.cpu_utilization > self.max_cpu_utilization {
1569 return Ok(Some(PolicyAction::ScaleUp));
1570 }
1571
1572 if metrics.memory_utilization > self.max_memory_utilization {
1573 return Ok(Some(PolicyAction::ScaleUp));
1574 }
1575
1576 if (1.0 - metrics.cache_miss_rate) < self.min_cache_efficiency {
1577 return Ok(Some(PolicyAction::Optimize));
1578 }
1579
1580 if metrics.cpu_utilization < 0.3 && metrics.memory_utilization < 0.3 {
1582 return Ok(Some(PolicyAction::ScaleDown));
1583 }
1584
1585 Ok(None)
1586 }
1587}
1588
1589#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1591pub enum PolicyAction {
1592 ScaleUp,
1593 ScaleDown,
1594 Optimize,
1595 Alert,
1596}
1597
1598#[derive(Debug, Clone)]
1600pub struct TuningRecommendation {
1601 pub category: RecommendationCategory,
1602 pub title: String,
1603 pub description: String,
1604 pub priority: RecommendationPriority,
1605 pub estimated_impact: ImpactLevel,
1606}
1607
1608#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1609pub enum RecommendationCategory {
1610 Performance,
1611 Resource,
1612 Stability,
1613 Security,
1614}
1615
1616#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1617pub enum RecommendationPriority {
1618 Low,
1619 Medium,
1620 High,
1621 Critical,
1622}
1623
1624#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1625pub enum ImpactLevel {
1626 Low,
1627 Medium,
1628 High,
1629}
1630
1631#[cfg(test)]
1632mod tests {
1633 use super::*;
1634
1635 #[test]
1636 fn test_resource_manager_creation() {
1637 let manager = ResourceManager::new().unwrap();
1638 {
1640 let mut monitor = manager.monitor.lock().unwrap();
1641 monitor.collect_metrics().unwrap();
1642 }
1643 assert!(manager.get_utilization().is_ok());
1644 }
1645
1646 #[test]
1647 fn test_adaptive_allocator() {
1648 let profile = PerformanceProfile::detect();
1649 let mut allocator = AdaptiveAllocator::new(profile).unwrap();
1650
1651 let allocation = allocator
1652 .allocate_optimized::<f64>(1000, WorkloadType::LinearAlgebra)
1653 .unwrap();
1654 assert_eq!(allocation.size(), 1000);
1655 assert!(allocation.is_cache_aligned());
1656 }
1657
1658 #[test]
1659 fn test_auto_tuner() {
1660 let profile = PerformanceProfile::detect();
1661 let mut tuner = AutoTuner::new(profile).unwrap();
1662
1663 for i in 0..6 {
1665 let metrics = ResourceMetrics {
1666 timestamp: Instant::now(),
1667 cpu_utilization: 0.9 + (0 as f64 * 0.01f64), memory_utilization: 0.7f64,
1669 cache_miss_rate: 0.15f64,
1670 operations_per_second: 500.0 - (0 as f64 * 10.0f64), memorybandwidth_usage: 0.5f64,
1672 thread_contention: 0.2f64,
1673 };
1674 tuner.adaptive_optimization(&metrics).unwrap();
1675 }
1676
1677 let recommendations = tuner.get_recommendations().unwrap();
1678 assert!(recommendations.len() < 1000); }
1684
1685 #[test]
1686 fn test_resourcemonitor() {
1687 let mut monitor = ResourceMonitor::new().unwrap();
1688 let metrics = monitor.collect_metrics().unwrap();
1689
1690 assert!(metrics.cpu_utilization >= 0.0 && metrics.cpu_utilization <= 1.0f64);
1691 assert!(metrics.memory_utilization >= 0.0 && metrics.memory_utilization <= 1.0f64);
1692 }
1693
1694 #[test]
1695 fn test_resourcepolicies() {
1696 let policies = ResourcePolicies::default();
1697 let metrics = ResourceMetrics {
1698 timestamp: Instant::now(),
1699 cpu_utilization: 0.95f64, memory_utilization: 0.5f64,
1701 cache_miss_rate: 0.05f64,
1702 operations_per_second: 1000.0f64,
1703 memorybandwidth_usage: 0.3f64,
1704 thread_contention: 0.1f64,
1705 };
1706
1707 let action = policies.check_violations(&metrics).unwrap();
1708 assert_eq!(action, Some(PolicyAction::ScaleUp));
1709 }
1710}