1pub mod auto_tuning;
13pub mod cpu;
14pub mod gpu;
15pub mod memory;
16pub mod network;
17pub mod optimization;
18pub mod storage;
19
20use crate::error::{CoreError, CoreResult};
21use std::time::Duration;
23
24#[derive(Debug, Clone)]
26pub struct SystemResources {
27 pub cpu: cpu::CpuInfo,
29 pub memory: memory::MemoryInfo,
31 pub gpu: Option<gpu::GpuInfo>,
33 pub network: network::NetworkInfo,
35 pub storage: storage::StorageInfo,
37 pub optimization_params: optimization::OptimizationParams,
39}
40
41impl SystemResources {
42 pub fn discover() -> CoreResult<Self> {
44 let cpu = cpu::CpuInfo::detect()?;
45 let memory = memory::MemoryInfo::detect()?;
46 let gpu = gpu::GpuInfo::detect().ok();
47 let network = network::NetworkInfo::detect()?;
48 let storage = storage::StorageInfo::detect()?;
49
50 let optimization_params = optimization::OptimizationParams::generate(
51 &cpu,
52 &memory,
53 gpu.as_ref(),
54 &network,
55 &storage,
56 )?;
57
58 Ok(Self {
59 cpu,
60 memory,
61 gpu,
62 network,
63 storage,
64 optimization_params,
65 })
66 }
67
68 pub fn recommended_thread_count(&self) -> usize {
70 self.optimization_params.thread_count
71 }
72
73 pub fn recommended_chunk_size(&self) -> usize {
75 self.optimization_params.chunk_size
76 }
77
78 pub fn supports_simd(&self) -> bool {
80 self.cpu.simd_capabilities.avx2 || self.cpu.simd_capabilities.sse4_2
81 }
82
83 pub fn supports_gpu(&self) -> bool {
85 self.gpu.is_some()
86 }
87
88 pub fn total_memory(&self) -> usize {
90 self.memory.total_memory
91 }
92
93 pub fn available_memory(&self) -> usize {
95 self.memory.available_memory
96 }
97
98 pub fn performance_tier(&self) -> PerformanceTier {
100 let cpu_score = self.cpu.performance_score();
101 let memory_score = self.memory.performance_score();
102 let gpu_score = self
103 .gpu
104 .as_ref()
105 .map(|g| g.performance_score())
106 .unwrap_or(0.0);
107
108 let combined_score = (cpu_score + memory_score + gpu_score) / 3.0;
109
110 if combined_score >= 0.8 {
111 PerformanceTier::High
112 } else if combined_score >= 0.5 {
113 PerformanceTier::Medium
114 } else {
115 PerformanceTier::Low
116 }
117 }
118
119 pub fn summary_report(&self) -> String {
121 let mut report = String::new();
122
123 report.push_str("# System Resource Summary\n\n");
124
125 report.push_str("## CPU\n");
127 report.push_str(&format!("- Model: {}\n", self.cpu.model));
128 report.push_str(&format!(
129 "- Cores: {} physical, {} logical\n",
130 self.cpu.physical_cores, self.cpu.logical_cores
131 ));
132 report.push_str(&format!(
133 "- Base frequency: {:.2} GHz\n",
134 self.cpu.base_frequency_ghz
135 ));
136 report.push_str(&format!(
137 "- Cache L1: {} KB, L2: {} KB, L3: {} KB\n",
138 self.cpu.cache_l1_kb, self.cpu.cache_l2_kb, self.cpu.cache_l3_kb
139 ));
140
141 report.push_str("- SIMD support:");
143 if self.cpu.simd_capabilities.sse4_2 {
144 report.push_str(" SSE4.2");
145 }
146 if self.cpu.simd_capabilities.avx2 {
147 report.push_str(" AVX2");
148 }
149 if self.cpu.simd_capabilities.avx512 {
150 report.push_str(" AVX512");
151 }
152 if self.cpu.simd_capabilities.neon {
153 report.push_str(" NEON");
154 }
155 report.push('\n');
156
157 report.push_str("\n## Memory\n");
159 report.push_str(&format!(
160 "- Total: {:.2} GB\n",
161 self.memory.total_memory as f64 / (1024.0 * 1024.0 * 1024.0)
162 ));
163 report.push_str(&format!(
164 "- Available: {:.2} GB\n",
165 self.memory.available_memory as f64 / (1024.0 * 1024.0 * 1024.0)
166 ));
167 report.push_str(&format!(
168 "- Page size: {} KB\n",
169 self.memory.page_size / 1024
170 ));
171
172 if let Some(ref gpu) = self.gpu {
174 report.push_str("\n## GPU\n");
175 report.push_str(&format!("- Model: {}\n", gpu.name));
176 report.push_str(&format!(
177 "- Memory: {:.2} GB\n",
178 gpu.memory_total as f64 / (1024.0 * 1024.0 * 1024.0)
179 ));
180 report.push_str(&format!("- Compute units: {}\n", gpu.compute_units));
181 }
182
183 report.push_str("\n## Optimization Recommendations\n");
185 report.push_str(&format!(
186 "- Thread count: {}\n",
187 self.optimization_params.thread_count
188 ));
189 report.push_str(&format!(
190 "- Chunk size: {} KB\n",
191 self.optimization_params.chunk_size / 1024
192 ));
193 report.push_str(&format!(
194 "- SIMD enabled: {}\n",
195 self.optimization_params.enable_simd
196 ));
197 report.push_str(&format!(
198 "- GPU enabled: {}\n",
199 self.optimization_params.enable_gpu
200 ));
201
202 report.push_str(&format!(
204 "\n## Performance Tier: {:?}\n",
205 self.performance_tier()
206 ));
207
208 report
209 }
210}
211
212#[derive(Debug, Clone, Copy, PartialEq, Eq)]
214pub enum PerformanceTier {
215 High,
217 Medium,
219 Low,
221}
222
223#[derive(Debug, Clone)]
225pub struct DiscoveryConfig {
226 pub detect_cpu: bool,
228 pub detect_memory: bool,
230 pub detect_gpu: bool,
232 pub detect_network: bool,
234 pub detectstorage: bool,
236 pub cache_results: bool,
238 pub cache_duration: Duration,
240 pub detailed_detection: bool,
242}
243
244impl Default for DiscoveryConfig {
245 fn default() -> Self {
246 Self {
247 detect_cpu: true,
248 detect_memory: true,
249 detect_gpu: true,
250 detect_network: true,
251 detectstorage: true,
252 cache_results: true,
253 cache_duration: Duration::from_secs(300), detailed_detection: false,
255 }
256 }
257}
258
259impl DiscoveryConfig {
260 pub fn new() -> Self {
262 Self::default()
263 }
264
265 pub fn detect_all(mut self) -> Self {
267 self.detect_cpu = true;
268 self.detect_memory = true;
269 self.detect_gpu = true;
270 self.detect_network = true;
271 self.detectstorage = true;
272 self
273 }
274
275 pub fn detect_none(mut self) -> Self {
277 self.detect_cpu = false;
278 self.detect_memory = false;
279 self.detect_gpu = false;
280 self.detect_network = false;
281 self.detectstorage = false;
282 self
283 }
284
285 pub fn detect_essential(mut self) -> Self {
287 self.detect_cpu = true;
288 self.detect_memory = true;
289 self.detect_gpu = false;
290 self.detect_network = false;
291 self.detectstorage = false;
292 self
293 }
294
295 pub fn with_cache_duration(mut self, duration: Duration) -> Self {
297 self.cache_results = true;
298 self.cache_duration = duration;
299 self
300 }
301
302 pub fn with_detailed_detection(mut self, enabled: bool) -> Self {
304 self.detailed_detection = enabled;
305 self
306 }
307}
308
309pub struct ResourceDiscovery {
311 config: DiscoveryConfig,
312 cached_resources: std::sync::Mutex<Option<(SystemResources, std::time::Instant)>>,
313}
314
315impl ResourceDiscovery {
316 pub fn new(config: DiscoveryConfig) -> Self {
318 Self {
319 config,
320 cached_resources: std::sync::Mutex::new(None),
321 }
322 }
323}
324
325impl Default for ResourceDiscovery {
326 fn default() -> Self {
327 Self::new(DiscoveryConfig::default())
328 }
329}
330
331impl ResourceDiscovery {
332 pub fn discover(&self) -> CoreResult<SystemResources> {
334 if self.config.cache_results {
335 if let Ok(cache) = self.cached_resources.lock() {
336 if let Some((ref resources, timestamp)) = *cache {
337 if timestamp.elapsed() < self.config.cache_duration {
338 return Ok(resources.clone());
339 }
340 }
341 }
342 }
343
344 let resources = self.discover_fresh()?;
346
347 if self.config.cache_results {
349 if let Ok(mut cache) = self.cached_resources.lock() {
350 *cache = Some((resources.clone(), std::time::Instant::now()));
351 }
352 }
353
354 Ok(resources)
355 }
356
357 pub fn discover_fresh(&self) -> CoreResult<SystemResources> {
359 let cpu = if self.config.detect_cpu {
360 cpu::CpuInfo::detect()?
361 } else {
362 cpu::CpuInfo::default()
363 };
364
365 let memory = if self.config.detect_memory {
366 memory::MemoryInfo::detect()?
367 } else {
368 memory::MemoryInfo::default()
369 };
370
371 let gpu = if self.config.detect_gpu {
372 gpu::GpuInfo::detect().ok()
373 } else {
374 None
375 };
376
377 let network = if self.config.detect_network {
378 network::NetworkInfo::detect()?
379 } else {
380 network::NetworkInfo::default()
381 };
382
383 let storage = if self.config.detectstorage {
384 storage::StorageInfo::detect()?
385 } else {
386 storage::StorageInfo::default()
387 };
388
389 let optimization_params = optimization::OptimizationParams::generate(
390 &cpu,
391 &memory,
392 gpu.as_ref(),
393 &network,
394 &storage,
395 )?;
396
397 Ok(SystemResources {
398 cpu,
399 memory,
400 gpu,
401 network,
402 storage,
403 optimization_params,
404 })
405 }
406
407 pub fn clear_cache(&self) -> CoreResult<()> {
409 if let Ok(mut cache) = self.cached_resources.lock() {
410 *cache = None;
411 Ok(())
412 } else {
413 Err(CoreError::ComputationError(
414 crate::error::ErrorContext::new("Failed to clear cache"),
415 ))
416 }
417 }
418
419 pub fn cache_status(&self) -> CoreResult<Option<Duration>> {
421 if let Ok(cache) = self.cached_resources.lock() {
422 if let Some((_, timestamp)) = cache.as_ref() {
423 Ok(Some(timestamp.elapsed()))
424 } else {
425 Ok(None)
426 }
427 } else {
428 Err(CoreError::ComputationError(
429 crate::error::ErrorContext::new("Failed to read cache status"),
430 ))
431 }
432 }
433}
434
435static GLOBAL_RESOURCE_DISCOVERY: std::sync::LazyLock<ResourceDiscovery> =
437 std::sync::LazyLock::new(ResourceDiscovery::default);
438
439#[allow(dead_code)]
441pub fn global_resource_discovery() -> &'static ResourceDiscovery {
442 &GLOBAL_RESOURCE_DISCOVERY
443}
444
445#[allow(dead_code)]
448pub fn get_system_resources() -> CoreResult<SystemResources> {
449 global_resource_discovery().discover()
450}
451
452#[allow(dead_code)]
454pub fn get_recommended_thread_count() -> CoreResult<usize> {
455 Ok(get_system_resources()?.recommended_thread_count())
456}
457
458#[allow(dead_code)]
460pub fn get_recommended_chunk_size() -> CoreResult<usize> {
461 Ok(get_system_resources()?.recommended_chunk_size())
462}
463
464#[allow(dead_code)]
466pub fn is_simd_supported() -> CoreResult<bool> {
467 Ok(get_system_resources()?.supports_simd())
468}
469
470#[allow(dead_code)]
472pub fn is_gpu_available() -> CoreResult<bool> {
473 Ok(get_system_resources()?.supports_gpu())
474}
475
476#[allow(dead_code)]
478pub fn get_total_memory() -> CoreResult<usize> {
479 Ok(get_system_resources()?.total_memory())
480}
481
482#[allow(dead_code)]
484pub fn get_available_memory() -> CoreResult<usize> {
485 Ok(get_system_resources()?.available_memory())
486}
487
488#[allow(dead_code)]
490pub fn get_performance_tier() -> CoreResult<PerformanceTier> {
491 Ok(get_system_resources()?.performance_tier())
492}
493
494pub struct ResourceMonitor {
496 discovery: ResourceDiscovery,
497 monitoring_interval: Duration,
498 last_update: std::sync::Mutex<std::time::Instant>,
499 adaptive_params: std::sync::Mutex<optimization::OptimizationParams>,
500}
501
502impl ResourceMonitor {
503 pub fn new(config: DiscoveryConfig, monitoringinterval: Duration) -> Self {
505 let discovery = ResourceDiscovery::new(config);
506
507 Self {
508 discovery,
509 monitoring_interval: monitoringinterval,
510 last_update: std::sync::Mutex::new(std::time::Instant::now()),
511 adaptive_params: std::sync::Mutex::new(optimization::OptimizationParams::default()),
512 }
513 }
514
515 pub fn update_optimization_params(&self) -> CoreResult<optimization::OptimizationParams> {
517 let should_update = {
518 if let Ok(last_update) = self.last_update.lock() {
519 last_update.elapsed() >= self.monitoring_interval
520 } else {
521 true
522 }
523 };
524
525 if should_update {
526 let resources = self.discovery.discover_fresh()?;
527
528 if let Ok(mut params) = self.adaptive_params.lock() {
530 *params = resources.optimization_params.clone();
531 }
532
533 if let Ok(mut last_update) = self.last_update.lock() {
535 *last_update = std::time::Instant::now();
536 }
537
538 Ok(resources.optimization_params)
539 } else {
540 if let Ok(params) = self.adaptive_params.lock() {
542 Ok(params.clone())
543 } else {
544 Err(CoreError::ComputationError(
545 crate::error::ErrorContext::new("Failed to read adaptive parameters"),
546 ))
547 }
548 }
549 }
550
551 pub fn current_params(&self) -> CoreResult<optimization::OptimizationParams> {
553 if let Ok(params) = self.adaptive_params.lock() {
554 Ok(params.clone())
555 } else {
556 Err(CoreError::ComputationError(
557 crate::error::ErrorContext::new("Failed to read current parameters"),
558 ))
559 }
560 }
561}
562
563#[cfg(test)]
564mod tests {
565 use super::*;
566
567 #[test]
568 fn test_discovery_config() {
569 let config = DiscoveryConfig::new()
570 .detect_essential()
571 .with_cache_duration(Duration::from_secs(60))
572 .with_detailed_detection(true);
573
574 assert!(config.detect_cpu);
575 assert!(config.detect_memory);
576 assert!(!config.detect_gpu);
577 assert_eq!(config.cache_duration, Duration::from_secs(60));
578 assert!(config.detailed_detection);
579 }
580
581 #[test]
582 fn test_performance_tier() {
583 assert_eq!(PerformanceTier::High, PerformanceTier::High);
584 assert_ne!(PerformanceTier::High, PerformanceTier::Low);
585 }
586
587 #[test]
588 fn test_resource_discovery() {
589 let config = DiscoveryConfig::new().detect_essential();
590 let discovery = ResourceDiscovery::new(config);
591
592 let resources = discovery.discover();
594 assert!(resources.is_ok());
595 }
596
597 #[test]
598 fn test_global_functions() {
599 let thread_count = get_recommended_thread_count();
601 assert!(thread_count.is_ok());
602 assert!(thread_count.unwrap() > 0);
603
604 let chunk_size = get_recommended_chunk_size();
605 assert!(chunk_size.is_ok());
606 assert!(chunk_size.unwrap() > 0);
607 }
608
609 #[test]
610 fn test_resourcemonitor() {
611 let config = DiscoveryConfig::new().detect_essential();
612 let monitor = ResourceMonitor::new(config, Duration::from_secs(1));
613
614 let params = monitor.update_optimization_params();
615 assert!(params.is_ok());
616
617 let current = monitor.current_params();
618 assert!(current.is_ok());
619 }
620}