1use std::collections::HashMap;
6use std::sync::{Arc, Mutex};
7use std::time::{Duration, Instant};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
11pub enum ResourceType {
12 CPU,
13 Memory,
14 Disk,
15 Network,
16 Database,
17 Cache,
18 Custom(u32),
19}
20
21#[derive(Debug, Clone, PartialEq)]
23pub enum OptimizationStatus {
24 NotOptimized,
25 Optimizing,
26 Optimized,
27 Failed,
28}
29
30#[derive(Debug, Clone)]
32#[allow(dead_code)]
33pub struct PerformanceMetrics {
34 resource_type: ResourceType,
35 utilization: f64,
36 throughput: f64,
37 latency: Duration,
38 metrics: HashMap<String, f64>,
39 last_updated: Instant,
40}
41
42#[derive(Debug, Clone)]
44#[allow(dead_code)]
45pub struct OptimizationConfig {
46 resource_type: ResourceType,
47 name: String,
48 status: OptimizationStatus,
49 settings: HashMap<String, String>,
50 target_utilization: f64,
51 target_throughput: f64,
52 target_latency: Duration,
53 last_modified: Instant,
54}
55
56pub struct PerformanceOptimizer {
58 resources: Arc<Mutex<HashMap<String, OptimizationConfig>>>,
59 metrics: Arc<Mutex<HashMap<String, PerformanceMetrics>>>,
60 input_counter: Arc<Mutex<usize>>,
61 auto_save_frequency: usize,
62}
63
64impl PerformanceOptimizer {
65 pub fn new(auto_save_frequency: usize) -> Self {
67 Self {
68 resources: Arc::new(Mutex::new(HashMap::new())),
69 metrics: Arc::new(Mutex::new(HashMap::new())),
70 input_counter: Arc::new(Mutex::new(0)),
71 auto_save_frequency,
72 }
73 }
74
75 pub fn configure_resource(
77 &self,
78 resource_name: &str,
79 resource_type: ResourceType,
80 settings: HashMap<String, String>,
81 target_utilization: f64,
82 target_throughput: f64,
83 target_latency: Duration,
84 ) -> Result<(), String> {
85 {
86 let mut resources = self
87 .resources
88 .lock()
89 .map_err(|e| format!("Mutex lock error: {e}"))?;
90
91 let config = OptimizationConfig {
92 resource_type,
93 name: resource_name.to_string(),
94 status: OptimizationStatus::NotOptimized,
95 settings,
96 target_utilization,
97 target_throughput,
98 target_latency,
99 last_modified: Instant::now(),
100 };
101
102 resources.insert(resource_name.to_string(), config);
103 } let _ = self.record_input_and_check_save();
107
108 Ok(())
109 }
110
111 pub fn update_metrics(
113 &self,
114 resource_name: &str,
115 utilization: f64,
116 throughput: f64,
117 latency: Duration,
118 additional_metrics: HashMap<String, f64>,
119 ) -> Result<(), String> {
120 let resource_type = {
122 let resources = self
123 .resources
124 .lock()
125 .map_err(|e| format!("Mutex lock error: {e}"))?;
126 if !resources.contains_key(resource_name) {
127 return Err(format!("Resource not found: {resource_name}"));
128 }
129 resources
130 .get(resource_name)
131 .ok_or(format!("Resource not found: {resource_name}"))?
132 .resource_type
133 };
134
135 {
137 let mut metrics_map = self
138 .metrics
139 .lock()
140 .map_err(|e| format!("Mutex lock error: {e}"))?;
141
142 let metrics = PerformanceMetrics {
143 resource_type,
144 utilization,
145 throughput,
146 latency,
147 metrics: additional_metrics,
148 last_updated: Instant::now(),
149 };
150
151 metrics_map.insert(resource_name.to_string(), metrics);
152 } let _ = self.record_input_and_check_save();
156
157 Ok(())
158 }
159
160 fn record_input_and_check_save(&self) -> Result<(), String> {
162 let mut counter = self
163 .input_counter
164 .lock()
165 .map_err(|e| format!("Mutex lock error: {e}"))?;
166 *counter += 1;
167
168 if *counter % self.auto_save_frequency == 0 {
170 match self.save_state_to_memory() {
171 Ok(_) => println!("Auto-saved performance state after {} changes", *counter),
172 Err(e) => eprintln!("Failed to auto-save: {e}"),
173 }
174 }
175
176 Ok(())
177 }
178
179 fn save_state_to_memory(&self) -> Result<(), String> {
181 let resources = self
184 .resources
185 .lock()
186 .map_err(|e| format!("Mutex lock error: {e}"))?;
187 let metrics = self
188 .metrics
189 .lock()
190 .map_err(|e| format!("Mutex lock error: {e}"))?;
191
192 println!(
193 "In-memory performance snapshot created: {} resources, {} metrics",
194 resources.len(),
195 metrics.len()
196 );
197
198 Ok(())
200 }
201
202 pub fn optimize_resource(&self, resource_name: &str) -> Result<OptimizationStatus, String> {
204 let status = {
206 let mut resources = self
207 .resources
208 .lock()
209 .map_err(|e| format!("Mutex lock error: {e}"))?;
210
211 let config = match resources.get_mut(resource_name) {
212 Some(config) => config,
213 None => return Err(format!("Resource not found: {resource_name}")),
214 };
215
216 let metrics = {
218 let metrics_map = self
219 .metrics
220 .lock()
221 .map_err(|e| format!("Mutex lock error: {e}"))?;
222 match metrics_map.get(resource_name) {
223 Some(metrics) => metrics.clone(),
224 None => {
225 return Err(format!(
226 "No metrics available for resource: {resource_name}"
227 ))
228 }
229 }
230 };
231
232 println!(
234 "Optimizing resource {}: {:?}",
235 resource_name, config.resource_type
236 );
237
238 let mut optimized = true;
240
241 if metrics.utilization > config.target_utilization {
242 println!(
243 " - High utilization: {:.2}% (target: {:.2}%)",
244 metrics.utilization * 100.0,
245 config.target_utilization * 100.0
246 );
247 optimized = false;
248 }
249
250 if metrics.throughput < config.target_throughput {
251 println!(
252 " - Low throughput: {:.2} (target: {:.2})",
253 metrics.throughput, config.target_throughput
254 );
255 optimized = false;
256 }
257
258 if metrics.latency > config.target_latency {
259 println!(
260 " - High latency: {:?} (target: {:?})",
261 metrics.latency, config.target_latency
262 );
263 optimized = false;
264 }
265
266 config.status = if optimized {
268 OptimizationStatus::Optimized
269 } else {
270 println!(" - Applying optimizations...");
272 OptimizationStatus::Optimized
273 };
274
275 config.last_modified = Instant::now();
276 config.status.clone()
277 }; let _ = self.record_input_and_check_save();
281
282 Ok(status)
283 }
284
285 pub fn optimize_all_resources(&self) -> HashMap<String, Result<OptimizationStatus, String>> {
287 let resource_names = match self.resources.lock() {
288 Ok(resources) => {
289 let names: Vec<String> = resources.keys().cloned().collect();
290 drop(resources); names
292 }
293 Err(e) => {
294 let mut map = HashMap::new();
296 map.insert("general".to_string(), Err(format!("Mutex lock error: {e}")));
297 return map;
298 }
299 };
300
301 let mut results = HashMap::new();
303 for name in resource_names {
304 results.insert(name.clone(), self.optimize_resource(&name));
305 }
306
307 results
308 }
309
310 pub fn get_resource_config(&self, resource_name: &str) -> Option<OptimizationConfig> {
312 match self.resources.lock() {
313 Ok(resources) => resources.get(resource_name).cloned(),
314 Err(e) => {
315 eprintln!("Mutex lock error: {e}");
316 None
317 }
318 }
319 }
320
321 pub fn get_resource_metrics(&self, resource_name: &str) -> Option<PerformanceMetrics> {
323 match self.metrics.lock() {
324 Ok(metrics) => metrics.get(resource_name).cloned(),
325 Err(e) => {
326 eprintln!("Mutex lock error: {e}");
327 None
328 }
329 }
330 }
331
332 pub fn get_all_resources(&self) -> Vec<OptimizationConfig> {
334 match self.resources.lock() {
335 Ok(resources) => resources.values().cloned().collect(),
336 Err(e) => {
337 eprintln!("Mutex lock error: {e}");
338 Vec::new()
339 }
340 }
341 }
342
343 pub fn get_all_metrics(&self) -> Vec<PerformanceMetrics> {
345 match self.metrics.lock() {
346 Ok(metrics) => metrics.values().cloned().collect(),
347 Err(e) => {
348 eprintln!("Mutex lock error: {e}");
349 Vec::new()
350 }
351 }
352 }
353
354 pub fn get_stats(&self) -> (usize, usize, usize) {
356 let counter = match self.input_counter.lock() {
357 Ok(counter) => *counter,
358 Err(e) => {
359 eprintln!("Mutex lock error for counter: {e}");
360 0
361 }
362 };
363
364 let resources_len = match self.resources.lock() {
365 Ok(resources) => resources.len(),
366 Err(e) => {
367 eprintln!("Mutex lock error for resources: {e}");
368 0
369 }
370 };
371
372 let metrics_len = match self.metrics.lock() {
373 Ok(metrics) => metrics.len(),
374 Err(e) => {
375 eprintln!("Mutex lock error for metrics: {e}");
376 0
377 }
378 };
379
380 (counter, resources_len, metrics_len)
381 }
382}
383
384#[cfg(test)]
386mod tests {
387 use super::*;
388
389 #[test]
390 fn test_resource_configuration_and_auto_save() -> Result<(), Box<dyn std::error::Error>> {
391 let optimizer = PerformanceOptimizer::new(20); for i in 0..25 {
395 let mut settings = HashMap::new();
396 settings.insert("max_connections".to_string(), "100".to_string());
397 settings.insert("timeout".to_string(), "5000".to_string());
398
399 optimizer.configure_resource(
400 &format!("resource_{i}"),
401 ResourceType::CPU,
402 settings,
403 0.7,
404 1000.0,
405 Duration::from_millis(100),
406 )?;
407 }
408
409 let (changes, resources, _) = optimizer.get_stats();
411 assert_eq!(changes, 25);
412 assert_eq!(resources, 25);
413
414 Ok(())
415 }
416
417 #[test]
418 fn test_optimization_workflow() -> Result<(), Box<dyn std::error::Error>> {
419 let optimizer = PerformanceOptimizer::new(10);
420
421 let mut settings = HashMap::new();
423 settings.insert("cache_size".to_string(), "1024".to_string());
424
425 optimizer.configure_resource(
426 "database",
427 ResourceType::Database,
428 settings,
429 0.8,
430 500.0,
431 Duration::from_millis(50),
432 )?;
433
434 let mut additional_metrics = HashMap::new();
436 additional_metrics.insert("cache_hits".to_string(), 0.75);
437 additional_metrics.insert("query_count".to_string(), 1500.0);
438
439 optimizer.update_metrics(
440 "database",
441 0.9, 450.0, Duration::from_millis(60), additional_metrics,
445 )?;
446
447 let result = optimizer.optimize_resource("database")?;
449 assert_eq!(result, OptimizationStatus::Optimized);
450
451 if let Some(config) = optimizer.get_resource_config("database") {
453 assert_eq!(config.status, OptimizationStatus::Optimized);
454 } else {
455 return Err("Resource config not found".into());
456 }
457
458 Ok(())
459 }
460}