Skip to main content

memscope_rs/capture/backends/
resource_ranking.rs

1//! Resource ranking and optimization recommendations
2//!
3//! This module provides comprehensive resource ranking capabilities,
4//! including multi-dimensional resource comparison and optimization suggestions.
5
6use serde::{Deserialize, Serialize};
7
8/// Resource ranking entry
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct ResourceRanking {
11    /// Task ID
12    pub task_id: u64,
13    /// Task name
14    pub task_name: String,
15    /// Task type
16    pub task_type: String,
17    /// CPU usage percentage
18    pub cpu_usage: f64,
19    /// Memory usage in MB
20    pub memory_usage_mb: f64,
21    /// I/O usage in MB
22    pub io_usage_mb: f64,
23    /// Network usage in MB
24    pub network_usage_mb: f64,
25    /// GPU usage percentage
26    pub gpu_usage: f64,
27    /// Overall efficiency score (0.0 to 1.0)
28    pub overall_score: f64,
29    /// Resource efficiency scores
30    pub efficiency_scores: EfficiencyScores,
31    /// Optimization recommendations
32    pub recommendations: Vec<String>,
33}
34
35/// Efficiency scores for different resources
36#[derive(Debug, Clone, Serialize, Deserialize)]
37pub struct EfficiencyScores {
38    /// CPU efficiency score
39    pub cpu_efficiency: f64,
40    /// Memory efficiency score
41    pub memory_efficiency: f64,
42    /// I/O efficiency score
43    pub io_efficiency: f64,
44    /// Network efficiency score
45    pub network_efficiency: f64,
46    /// GPU efficiency score
47    pub gpu_efficiency: f64,
48}
49
50/// Task resource metrics for ranking analysis
51///
52/// This structure contains resource usage metrics for a task,
53/// used for calculating efficiency scores and generating optimization recommendations.
54#[derive(Debug, Clone, Serialize, Deserialize)]
55pub struct TaskResourceMetrics {
56    /// Unique identifier for the task
57    pub task_id: u64,
58    /// Human-readable task name
59    pub task_name: String,
60    /// Task type categorization
61    ///
62    /// Supported values (matching TaskType enum):
63    /// - "CpuIntensive": CPU-bound tasks (matrix multiplication, data processing)
64    /// - "IoIntensive": I/O-bound tasks (file operations, database queries)
65    /// - "NetworkIntensive": Network-bound tasks (HTTP requests, RPC calls)
66    /// - "MemoryIntensive": Memory-bound tasks (large data structures, caching)
67    /// - "GpuCompute": GPU compute tasks (CUDA, OpenCL operations)
68    /// - "Mixed": Balanced workload across multiple resources
69    /// - "Streaming": Continuous data processing tasks
70    /// - "Background": Maintenance and cleanup tasks
71    pub task_type: String,
72    /// CPU usage percentage (0.0 to 100.0)
73    pub cpu_usage: f64,
74    /// Memory usage in megabytes
75    pub memory_usage_mb: f64,
76    /// I/O usage in megabytes
77    pub io_usage_mb: f64,
78    /// Network usage in megabytes
79    pub network_usage_mb: f64,
80    /// GPU usage percentage (0.0 to 100.0)
81    pub gpu_usage: f64,
82}
83
84/// Resource usage for recommendations
85struct ResourceUsage {
86    cpu: f64,
87    memory: f64,
88    io: f64,
89    network: f64,
90    gpu: f64,
91}
92
93impl EfficiencyScores {
94    /// Create new efficiency scores
95    pub fn new(cpu: f64, memory: f64, io: f64, network: f64, gpu: f64) -> Self {
96        Self {
97            cpu_efficiency: cpu,
98            memory_efficiency: memory,
99            io_efficiency: io,
100            network_efficiency: network,
101            gpu_efficiency: gpu,
102        }
103    }
104
105    /// Calculate overall efficiency score
106    pub fn overall_score(&self, config: &RankingConfig) -> f64 {
107        let weighted_sum = self.cpu_efficiency * config.cpu_weight
108            + self.memory_efficiency * config.memory_weight
109            + self.io_efficiency * config.io_weight
110            + self.network_efficiency * config.network_weight
111            + self.gpu_efficiency * config.gpu_weight;
112
113        let total_weight = config.cpu_weight
114            + config.memory_weight
115            + config.io_weight
116            + config.network_weight
117            + config.gpu_weight;
118
119        if total_weight <= 0.0 {
120            0.0
121        } else {
122            weighted_sum / total_weight
123        }
124    }
125}
126
127/// Resource ranking configuration
128#[derive(Debug, Clone, Serialize, Deserialize)]
129pub struct RankingConfig {
130    /// Weight for CPU usage in overall score
131    pub cpu_weight: f64,
132    /// Weight for memory usage in overall score
133    pub memory_weight: f64,
134    /// Weight for I/O usage in overall score
135    pub io_weight: f64,
136    /// Weight for network usage in overall score
137    pub network_weight: f64,
138    /// Weight for GPU usage in overall score
139    pub gpu_weight: f64,
140    /// Enable optimization recommendations
141    pub enable_recommendations: bool,
142    /// Minimum efficiency score threshold for recommendations
143    pub min_efficiency_threshold: f64,
144}
145
146impl Default for RankingConfig {
147    fn default() -> Self {
148        Self {
149            cpu_weight: 0.3,
150            memory_weight: 0.3,
151            io_weight: 0.2,
152            network_weight: 0.1,
153            gpu_weight: 0.1,
154            enable_recommendations: true,
155            min_efficiency_threshold: 0.6,
156        }
157    }
158}
159
160/// Resource ranking analyzer
161pub struct ResourceRankingAnalyzer {
162    config: RankingConfig,
163    rankings: Vec<ResourceRanking>,
164}
165
166impl ResourceRankingAnalyzer {
167    /// Create new resource ranking analyzer with default configuration
168    pub fn new() -> Self {
169        Self {
170            config: RankingConfig::default(),
171            rankings: Vec::new(),
172        }
173    }
174
175    /// Create new resource ranking analyzer with custom configuration
176    pub fn with_config(config: RankingConfig) -> Self {
177        Self {
178            config,
179            rankings: Vec::new(),
180        }
181    }
182
183    /// Analyze and rank resources for a task
184    pub fn analyze_task(&mut self, metrics: &TaskResourceMetrics) -> ResourceRanking {
185        let efficiency_scores = EfficiencyScores::new(
186            self.calculate_cpu_efficiency(metrics.cpu_usage),
187            self.calculate_memory_efficiency(metrics.memory_usage_mb),
188            self.calculate_io_efficiency(metrics.io_usage_mb),
189            self.calculate_network_efficiency(metrics.network_usage_mb),
190            self.calculate_gpu_efficiency(metrics.gpu_usage),
191        );
192
193        let overall_score = self.calculate_overall_score(
194            metrics.cpu_usage,
195            metrics.memory_usage_mb,
196            metrics.io_usage_mb,
197            metrics.network_usage_mb,
198            metrics.gpu_usage,
199        );
200
201        let recommendations = if self.config.enable_recommendations {
202            self.generate_recommendations(
203                &efficiency_scores,
204                overall_score,
205                ResourceUsage {
206                    cpu: metrics.cpu_usage,
207                    memory: metrics.memory_usage_mb,
208                    io: metrics.io_usage_mb,
209                    network: metrics.network_usage_mb,
210                    gpu: metrics.gpu_usage,
211                },
212            )
213        } else {
214            Vec::new()
215        };
216
217        let ranking = ResourceRanking {
218            task_id: metrics.task_id,
219            task_name: metrics.task_name.clone(),
220            task_type: metrics.task_type.clone(),
221            cpu_usage: metrics.cpu_usage,
222            memory_usage_mb: metrics.memory_usage_mb,
223            io_usage_mb: metrics.io_usage_mb,
224            network_usage_mb: metrics.network_usage_mb,
225            gpu_usage: metrics.gpu_usage,
226            overall_score,
227            efficiency_scores,
228            recommendations,
229        };
230
231        self.rankings.push(ranking.clone());
232        ranking
233    }
234
235    /// Calculate CPU efficiency score
236    fn calculate_cpu_efficiency(&self, cpu_usage: f64) -> f64 {
237        if cpu_usage <= 0.0 {
238            return 0.0;
239        }
240
241        if cpu_usage <= 50.0 {
242            1.0
243        } else if cpu_usage <= 75.0 {
244            0.8
245        } else if cpu_usage <= 90.0 {
246            0.6
247        } else {
248            0.4
249        }
250    }
251
252    /// Calculate memory efficiency score
253    fn calculate_memory_efficiency(&self, memory_mb: f64) -> f64 {
254        if memory_mb <= 0.0 {
255            return 0.0;
256        }
257
258        if memory_mb <= 100.0 {
259            1.0
260        } else if memory_mb <= 500.0 {
261            0.8
262        } else if memory_mb <= 1000.0 {
263            0.6
264        } else {
265            0.4
266        }
267    }
268
269    /// Calculate I/O efficiency score
270    fn calculate_io_efficiency(&self, io_mb: f64) -> f64 {
271        if io_mb <= 0.0 {
272            return 0.0;
273        }
274
275        if io_mb <= 10.0 {
276            1.0
277        } else if io_mb <= 100.0 {
278            0.8
279        } else if io_mb <= 500.0 {
280            0.6
281        } else {
282            0.4
283        }
284    }
285
286    /// Calculate network efficiency score
287    fn calculate_network_efficiency(&self, network_mb: f64) -> f64 {
288        if network_mb <= 0.0 {
289            return 0.0;
290        }
291
292        if network_mb <= 10.0 {
293            1.0
294        } else if network_mb <= 100.0 {
295            0.8
296        } else if network_mb <= 500.0 {
297            0.6
298        } else {
299            0.4
300        }
301    }
302
303    /// Calculate GPU efficiency score
304    fn calculate_gpu_efficiency(&self, gpu_usage: f64) -> f64 {
305        if gpu_usage <= 0.0 {
306            return 0.0;
307        }
308
309        if gpu_usage <= 50.0 {
310            1.0
311        } else if gpu_usage <= 75.0 {
312            0.8
313        } else if gpu_usage <= 90.0 {
314            0.6
315        } else {
316            0.4
317        }
318    }
319
320    /// Calculate overall score
321    fn calculate_overall_score(
322        &self,
323        cpu_usage: f64,
324        memory_mb: f64,
325        io_mb: f64,
326        network_mb: f64,
327        gpu_usage: f64,
328    ) -> f64 {
329        let cpu_score = self.calculate_cpu_efficiency(cpu_usage);
330        let memory_score = self.calculate_memory_efficiency(memory_mb);
331        let io_score = self.calculate_io_efficiency(io_mb);
332        let network_score = self.calculate_network_efficiency(network_mb);
333        let gpu_score = self.calculate_gpu_efficiency(gpu_usage);
334
335        let weighted_sum = cpu_score * self.config.cpu_weight
336            + memory_score * self.config.memory_weight
337            + io_score * self.config.io_weight
338            + network_score * self.config.network_weight
339            + gpu_score * self.config.gpu_weight;
340
341        let total_weight = self.config.cpu_weight
342            + self.config.memory_weight
343            + self.config.io_weight
344            + self.config.network_weight
345            + self.config.gpu_weight;
346
347        weighted_sum / total_weight
348    }
349
350    /// Generate optimization recommendations
351    fn generate_recommendations(
352        &self,
353        efficiency: &EfficiencyScores,
354        overall_score: f64,
355        usage: ResourceUsage,
356    ) -> Vec<String> {
357        let mut recommendations = Vec::new();
358
359        if overall_score < self.config.min_efficiency_threshold {
360            recommendations.push(
361                "Overall efficiency is below threshold. Consider reviewing resource usage patterns.".to_string()
362            );
363        }
364
365        if efficiency.cpu_efficiency < 0.6 {
366            if usage.cpu > 90.0 {
367                recommendations.push(
368                    "CPU usage is critical (>90%). Consider parallelizing work or optimizing algorithms.".to_string()
369                );
370            } else if usage.cpu > 75.0 {
371                recommendations.push(
372                    "CPU usage is high (>75%). Profile hot paths and optimize critical sections."
373                        .to_string(),
374                );
375            }
376        }
377
378        if efficiency.memory_efficiency < 0.6 {
379            if usage.memory > 1000.0 {
380                recommendations.push(
381                    "Memory usage is high (>1GB). Implement memory pooling or reduce footprint."
382                        .to_string(),
383                );
384            } else if usage.memory > 500.0 {
385                recommendations.push(
386                    "Memory usage is moderate (>500MB). Consider optimizing data structures."
387                        .to_string(),
388                );
389            }
390        }
391
392        if efficiency.io_efficiency < 0.6 {
393            if usage.io > 500.0 {
394                recommendations.push(
395                    "I/O usage is high (>500MB). Implement buffering or async I/O.".to_string(),
396                );
397            } else if usage.io > 100.0 {
398                recommendations.push(
399                    "I/O usage is moderate (>100MB). Consider batching operations.".to_string(),
400                );
401            }
402        }
403
404        if efficiency.network_efficiency < 0.6 {
405            if usage.network > 500.0 {
406                recommendations.push(
407                    "Network usage is high (>500MB). Implement compression or connection pooling."
408                        .to_string(),
409                );
410            } else if usage.network > 100.0 {
411                recommendations.push(
412                    "Network usage is moderate (>100MB). Consider caching or batching requests."
413                        .to_string(),
414                );
415            }
416        }
417
418        if efficiency.gpu_efficiency < 0.6 {
419            if usage.gpu > 90.0 {
420                recommendations.push(
421                    "GPU usage is critical (>90%). Optimize kernel execution or reduce workload."
422                        .to_string(),
423                );
424            } else if usage.gpu > 75.0 {
425                recommendations.push(
426                    "GPU usage is high (>75%). Review compute kernel efficiency.".to_string(),
427                );
428            }
429        }
430
431        recommendations
432    }
433
434    /// Get all rankings sorted by overall score
435    pub fn get_rankings(&self) -> Vec<&ResourceRanking> {
436        let mut rankings: Vec<&ResourceRanking> = self.rankings.iter().collect();
437        rankings.sort_by(|a, b| {
438            b.overall_score
439                .partial_cmp(&a.overall_score)
440                .unwrap_or(std::cmp::Ordering::Equal)
441        });
442        rankings
443    }
444
445    /// Get top N rankings
446    pub fn get_top_rankings(&self, n: usize) -> Vec<&ResourceRanking> {
447        let mut rankings = self.get_rankings();
448        rankings.truncate(n);
449        rankings
450    }
451
452    /// Get bottom N rankings
453    pub fn get_bottom_rankings(&self, n: usize) -> Vec<&ResourceRanking> {
454        let mut rankings: Vec<&ResourceRanking> = self.rankings.iter().collect();
455        rankings.sort_by(|a, b| {
456            a.overall_score
457                .partial_cmp(&b.overall_score)
458                .unwrap_or(std::cmp::Ordering::Equal)
459        });
460        rankings.truncate(n);
461        rankings
462    }
463
464    /// Get rankings by task type
465    pub fn get_rankings_by_type(&self, task_type: &str) -> Vec<&ResourceRanking> {
466        self.rankings
467            .iter()
468            .filter(|r| r.task_type == task_type)
469            .collect()
470    }
471
472    /// Get analyzer configuration
473    pub fn config(&self) -> &RankingConfig {
474        &self.config
475    }
476
477    /// Update analyzer configuration
478    pub fn set_config(&mut self, config: RankingConfig) {
479        self.config = config;
480    }
481
482    /// Clear all rankings
483    pub fn clear(&mut self) {
484        self.rankings.clear();
485    }
486
487    /// Get statistics
488    pub fn get_statistics(&self) -> RankingStatistics {
489        if self.rankings.is_empty() {
490            return RankingStatistics::default();
491        }
492
493        let overall_scores: Vec<f64> = self.rankings.iter().map(|r| r.overall_score).collect();
494        let avg_score = overall_scores.iter().sum::<f64>() / overall_scores.len() as f64;
495        let max_score = overall_scores
496            .iter()
497            .cloned()
498            .fold(f64::NEG_INFINITY, f64::max);
499        let min_score = overall_scores.iter().cloned().fold(f64::INFINITY, f64::min);
500
501        let cpu_scores: Vec<f64> = self
502            .rankings
503            .iter()
504            .map(|r| r.efficiency_scores.cpu_efficiency)
505            .collect();
506        let avg_cpu = cpu_scores.iter().sum::<f64>() / cpu_scores.len() as f64;
507
508        let memory_scores: Vec<f64> = self
509            .rankings
510            .iter()
511            .map(|r| r.efficiency_scores.memory_efficiency)
512            .collect();
513        let avg_memory = memory_scores.iter().sum::<f64>() / memory_scores.len() as f64;
514
515        RankingStatistics {
516            total_tasks: self.rankings.len(),
517            average_overall_score: avg_score,
518            max_overall_score: max_score,
519            min_overall_score: min_score,
520            average_cpu_efficiency: avg_cpu,
521            average_memory_efficiency: avg_memory,
522        }
523    }
524}
525
526impl Default for ResourceRankingAnalyzer {
527    fn default() -> Self {
528        Self::new()
529    }
530}
531
532/// Resource ranking statistics
533#[derive(Debug, Clone, Serialize, Deserialize)]
534pub struct RankingStatistics {
535    /// Total number of tasks ranked
536    pub total_tasks: usize,
537    /// Average overall score
538    pub average_overall_score: f64,
539    /// Maximum overall score
540    pub max_overall_score: f64,
541    /// Minimum overall score
542    pub min_overall_score: f64,
543    /// Average CPU efficiency
544    pub average_cpu_efficiency: f64,
545    /// Average memory efficiency
546    pub average_memory_efficiency: f64,
547}
548
549impl Default for RankingStatistics {
550    fn default() -> Self {
551        Self {
552            total_tasks: 0,
553            average_overall_score: 0.0,
554            max_overall_score: 0.0,
555            min_overall_score: 0.0,
556            average_cpu_efficiency: 0.0,
557            average_memory_efficiency: 0.0,
558        }
559    }
560}
561
562#[cfg(test)]
563mod tests {
564    use super::*;
565
566    #[test]
567    fn test_efficiency_scores_creation() {
568        let scores = EfficiencyScores::new(0.8, 0.7, 0.9, 0.6, 0.5);
569        assert_eq!(scores.cpu_efficiency, 0.8);
570        assert_eq!(scores.memory_efficiency, 0.7);
571        assert_eq!(scores.io_efficiency, 0.9);
572        assert_eq!(scores.network_efficiency, 0.6);
573        assert_eq!(scores.gpu_efficiency, 0.5);
574    }
575
576    #[test]
577    fn test_efficiency_scores_overall() {
578        let scores = EfficiencyScores::new(0.8, 0.7, 0.9, 0.6, 0.5);
579        let config = RankingConfig::default();
580        let overall = scores.overall_score(&config);
581        let expected = (0.8 * 0.3 + 0.7 * 0.3 + 0.9 * 0.2 + 0.6 * 0.1 + 0.5 * 0.1) / 1.0;
582        assert!((overall - expected).abs() < 0.01);
583    }
584
585    #[test]
586    fn test_resource_ranking_analyzer_creation() {
587        let analyzer = ResourceRankingAnalyzer::new();
588        assert!(analyzer.rankings.is_empty());
589    }
590
591    #[test]
592    fn test_analyze_task() {
593        let mut analyzer = ResourceRankingAnalyzer::new();
594        let metrics = TaskResourceMetrics {
595            task_id: 1,
596            task_name: "test_task".to_string(),
597            task_type: "CpuIntensive".to_string(),
598            cpu_usage: 60.0,
599            memory_usage_mb: 200.0,
600            io_usage_mb: 50.0,
601            network_usage_mb: 30.0,
602            gpu_usage: 40.0,
603        };
604        let ranking = analyzer.analyze_task(&metrics);
605
606        assert_eq!(ranking.task_id, 1);
607        assert_eq!(ranking.task_name, "test_task");
608        assert!(ranking.overall_score > 0.0);
609    }
610
611    #[test]
612    fn test_get_rankings() {
613        let mut analyzer = ResourceRankingAnalyzer::new();
614        let metrics1 = TaskResourceMetrics {
615            task_id: 1,
616            task_name: "task1".to_string(),
617            task_type: "CpuIntensive".to_string(),
618            cpu_usage: 80.0,
619            memory_usage_mb: 200.0,
620            io_usage_mb: 50.0,
621            network_usage_mb: 30.0,
622            gpu_usage: 40.0,
623        };
624        let metrics2 = TaskResourceMetrics {
625            task_id: 2,
626            task_name: "task2".to_string(),
627            task_type: "CpuIntensive".to_string(),
628            cpu_usage: 40.0,
629            memory_usage_mb: 100.0,
630            io_usage_mb: 30.0,
631            network_usage_mb: 20.0,
632            gpu_usage: 30.0,
633        };
634        analyzer.analyze_task(&metrics1);
635        analyzer.analyze_task(&metrics2);
636
637        let rankings = analyzer.get_rankings();
638        assert_eq!(rankings.len(), 2);
639        assert!(rankings[0].overall_score >= rankings[1].overall_score);
640    }
641
642    #[test]
643    fn test_get_top_rankings() {
644        let mut analyzer = ResourceRankingAnalyzer::new();
645        let metrics1 = TaskResourceMetrics {
646            task_id: 1,
647            task_name: "task1".to_string(),
648            task_type: "CpuIntensive".to_string(),
649            cpu_usage: 80.0,
650            memory_usage_mb: 200.0,
651            io_usage_mb: 50.0,
652            network_usage_mb: 30.0,
653            gpu_usage: 40.0,
654        };
655        let metrics2 = TaskResourceMetrics {
656            task_id: 2,
657            task_name: "task2".to_string(),
658            task_type: "CpuIntensive".to_string(),
659            cpu_usage: 40.0,
660            memory_usage_mb: 100.0,
661            io_usage_mb: 30.0,
662            network_usage_mb: 20.0,
663            gpu_usage: 30.0,
664        };
665        let metrics3 = TaskResourceMetrics {
666            task_id: 3,
667            task_name: "task3".to_string(),
668            task_type: "CpuIntensive".to_string(),
669            cpu_usage: 60.0,
670            memory_usage_mb: 150.0,
671            io_usage_mb: 40.0,
672            network_usage_mb: 25.0,
673            gpu_usage: 35.0,
674        };
675        analyzer.analyze_task(&metrics1);
676        analyzer.analyze_task(&metrics2);
677        analyzer.analyze_task(&metrics3);
678
679        let top = analyzer.get_top_rankings(2);
680        assert_eq!(top.len(), 2);
681    }
682
683    #[test]
684    fn test_get_rankings_by_type() {
685        let mut analyzer = ResourceRankingAnalyzer::new();
686        let metrics1 = TaskResourceMetrics {
687            task_id: 1,
688            task_name: "task1".to_string(),
689            task_type: "CpuIntensive".to_string(),
690            cpu_usage: 60.0,
691            memory_usage_mb: 200.0,
692            io_usage_mb: 50.0,
693            network_usage_mb: 30.0,
694            gpu_usage: 40.0,
695        };
696        let metrics2 = TaskResourceMetrics {
697            task_id: 2,
698            task_name: "task2".to_string(),
699            task_type: "IoIntensive".to_string(),
700            cpu_usage: 40.0,
701            memory_usage_mb: 100.0,
702            io_usage_mb: 80.0,
703            network_usage_mb: 20.0,
704            gpu_usage: 30.0,
705        };
706        analyzer.analyze_task(&metrics1);
707        analyzer.analyze_task(&metrics2);
708
709        let cpu_rankings = analyzer.get_rankings_by_type("CpuIntensive");
710        assert_eq!(cpu_rankings.len(), 1);
711    }
712
713    #[test]
714    fn test_custom_config() {
715        let config = RankingConfig {
716            cpu_weight: 0.5,
717            memory_weight: 0.3,
718            io_weight: 0.1,
719            network_weight: 0.05,
720            gpu_weight: 0.05,
721            ..Default::default()
722        };
723        let analyzer = ResourceRankingAnalyzer::with_config(config);
724
725        assert_eq!(analyzer.config().cpu_weight, 0.5);
726        assert_eq!(analyzer.config().memory_weight, 0.3);
727    }
728
729    #[test]
730    fn test_clear() {
731        let mut analyzer = ResourceRankingAnalyzer::new();
732        let metrics = TaskResourceMetrics {
733            task_id: 1,
734            task_name: "task1".to_string(),
735            task_type: "CpuIntensive".to_string(),
736            cpu_usage: 60.0,
737            memory_usage_mb: 200.0,
738            io_usage_mb: 50.0,
739            network_usage_mb: 30.0,
740            gpu_usage: 40.0,
741        };
742        analyzer.analyze_task(&metrics);
743        analyzer.clear();
744
745        assert!(analyzer.rankings.is_empty());
746    }
747
748    #[test]
749    fn test_get_statistics() {
750        let mut analyzer = ResourceRankingAnalyzer::new();
751        let metrics1 = TaskResourceMetrics {
752            task_id: 1,
753            task_name: "task1".to_string(),
754            task_type: "CpuIntensive".to_string(),
755            cpu_usage: 60.0,
756            memory_usage_mb: 200.0,
757            io_usage_mb: 50.0,
758            network_usage_mb: 30.0,
759            gpu_usage: 40.0,
760        };
761        let metrics2 = TaskResourceMetrics {
762            task_id: 2,
763            task_name: "task2".to_string(),
764            task_type: "CpuIntensive".to_string(),
765            cpu_usage: 40.0,
766            memory_usage_mb: 100.0,
767            io_usage_mb: 30.0,
768            network_usage_mb: 20.0,
769            gpu_usage: 30.0,
770        };
771        analyzer.analyze_task(&metrics1);
772        analyzer.analyze_task(&metrics2);
773
774        let stats = analyzer.get_statistics();
775        assert_eq!(stats.total_tasks, 2);
776        assert!(stats.average_overall_score > 0.0);
777    }
778
779    #[test]
780    fn test_recommendations_generation() {
781        let mut analyzer = ResourceRankingAnalyzer::new();
782        let metrics = TaskResourceMetrics {
783            task_id: 1,
784            task_name: "test_task".to_string(),
785            task_type: "CpuIntensive".to_string(),
786            cpu_usage: 95.0,
787            memory_usage_mb: 1200.0,
788            io_usage_mb: 600.0,
789            network_usage_mb: 600.0,
790            gpu_usage: 95.0,
791        };
792        let ranking = analyzer.analyze_task(&metrics);
793
794        assert!(!ranking.recommendations.is_empty());
795    }
796}