memscope_rs/capture/backends/
efficiency_scoring.rs1use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone)]
10pub struct EfficiencyConfig {
11 pub enable_cpu_efficiency: bool,
13 pub enable_memory_efficiency: bool,
15 pub enable_io_efficiency: bool,
17 pub enable_network_efficiency: bool,
19 pub custom_weights: Option<EfficiencyWeights>,
21}
22
23impl Default for EfficiencyConfig {
24 fn default() -> Self {
25 Self {
26 enable_cpu_efficiency: true,
27 enable_memory_efficiency: true,
28 enable_io_efficiency: true,
29 enable_network_efficiency: true,
30 custom_weights: None,
31 }
32 }
33}
34
35impl EfficiencyConfig {
36 pub fn minimal() -> Self {
38 Self {
39 enable_cpu_efficiency: true,
40 enable_memory_efficiency: true,
41 enable_io_efficiency: false,
42 enable_network_efficiency: false,
43 custom_weights: None,
44 }
45 }
46
47 pub fn comprehensive() -> Self {
49 Self {
50 enable_cpu_efficiency: true,
51 enable_memory_efficiency: true,
52 enable_io_efficiency: true,
53 enable_network_efficiency: true,
54 custom_weights: None,
55 }
56 }
57}
58
59#[derive(Debug, Clone)]
61pub struct EfficiencyWeights {
62 pub cpu_weight: f64,
64 pub memory_weight: f64,
66 pub io_weight: f64,
68 pub network_weight: f64,
70}
71
72impl Default for EfficiencyWeights {
73 fn default() -> Self {
74 Self {
75 cpu_weight: 0.25,
76 memory_weight: 0.25,
77 io_weight: 0.25,
78 network_weight: 0.25,
79 }
80 }
81}
82
83#[derive(Debug, Clone, Serialize, Deserialize)]
85pub struct ComponentScores {
86 pub cpu_efficiency: f64,
88 pub memory_efficiency: f64,
90 pub io_efficiency: f64,
92 pub network_efficiency: f64,
94}
95
96impl Default for ComponentScores {
97 fn default() -> Self {
98 Self {
99 cpu_efficiency: 0.0,
100 memory_efficiency: 0.0,
101 io_efficiency: 0.0,
102 network_efficiency: 0.0,
103 }
104 }
105}
106
107impl ComponentScores {
108 pub fn overall(&self) -> f64 {
110 let sum = self.cpu_efficiency
111 + self.memory_efficiency
112 + self.io_efficiency
113 + self.network_efficiency;
114
115 let count = if self.cpu_efficiency > 0.0 { 1 } else { 0 }
116 + if self.memory_efficiency > 0.0 { 1 } else { 0 }
117 + if self.io_efficiency > 0.0 { 1 } else { 0 }
118 + if self.network_efficiency > 0.0 { 1 } else { 0 };
119
120 if count > 0 {
121 sum / count as f64
122 } else {
123 0.0
124 }
125 }
126}
127
128pub struct EfficiencyScorer {
130 config: EfficiencyConfig,
131}
132
133impl EfficiencyScorer {
134 pub fn new() -> Self {
136 Self {
137 config: EfficiencyConfig::default(),
138 }
139 }
140
141 pub fn with_config(config: EfficiencyConfig) -> Self {
143 Self { config }
144 }
145
146 pub fn calculate_efficiency(
148 &self,
149 profile: &crate::capture::backends::task_profile::TaskMemoryProfile,
150 cpu_usage_percent: f64,
151 io_bytes_processed: u64,
152 network_bytes_transferred: u64,
153 ) -> ComponentScores {
154 let cpu_efficiency = if self.config.enable_cpu_efficiency {
155 self.calculate_cpu_efficiency(cpu_usage_percent)
156 } else {
157 0.0
158 };
159
160 let memory_efficiency = if self.config.enable_memory_efficiency {
161 self.calculate_memory_efficiency(profile)
162 } else {
163 0.0
164 };
165
166 let io_efficiency = if self.config.enable_io_efficiency {
167 self.calculate_io_efficiency(io_bytes_processed)
168 } else {
169 0.0
170 };
171
172 let network_efficiency = if self.config.enable_network_efficiency {
173 self.calculate_network_efficiency(network_bytes_transferred)
174 } else {
175 0.0
176 };
177
178 ComponentScores {
179 cpu_efficiency,
180 memory_efficiency,
181 io_efficiency,
182 network_efficiency,
183 }
184 }
185
186 fn calculate_cpu_efficiency(&self, usage_percent: f64) -> f64 {
188 let usage = (usage_percent / 100.0).clamp(0.0, 1.0);
189
190 if usage <= 0.0 {
191 return 0.0;
192 }
193
194 let efficiency = if usage <= 0.5 {
195 usage * 2.0
196 } else if usage <= 0.8 {
197 0.5 + usage * 0.625
198 } else {
199 1.0
200 };
201
202 efficiency.clamp(0.0, 1.0)
203 }
204
205 fn calculate_memory_efficiency(
207 &self,
208 task_profile: &crate::capture::backends::task_profile::TaskMemoryProfile,
209 ) -> f64 {
210 if task_profile.total_bytes == 0 {
211 return 1.0;
212 }
213
214 let utilization = task_profile.current_memory as f64 / task_profile.total_bytes as f64;
215 let efficiency = 1.0 - utilization;
216
217 efficiency.clamp(0.0, 1.0)
218 }
219
220 fn calculate_io_efficiency(&self, bytes_processed: u64) -> f64 {
222 if bytes_processed == 0 {
223 return 0.0;
224 }
225
226 let optimal_size = 65536.0;
227 let efficiency = (bytes_processed as f64 / optimal_size).min(1.0);
228
229 efficiency.clamp(0.0, 1.0)
230 }
231
232 fn calculate_network_efficiency(&self, bytes_transferred: u64) -> f64 {
234 if bytes_transferred == 0 {
235 return 0.0;
236 }
237
238 let optimal_throughput = 1_048_576.0;
240 let efficiency = (bytes_transferred as f64 / optimal_throughput).min(1.0);
241
242 efficiency.clamp(0.0, 1.0)
243 }
244
245 pub fn calculate_weighted_efficiency(
247 &self,
248 task_type: &crate::capture::backends::task_profile::TaskType,
249 component_scores: &ComponentScores,
250 ) -> f64 {
251 let weights = self.config.custom_weights.as_ref().map_or_else(
252 || Self::default_weights_for_task_type(task_type),
253 |w| w.clone(),
254 );
255
256 let weighted_score = component_scores.cpu_efficiency * weights.cpu_weight
257 + component_scores.memory_efficiency * weights.memory_weight
258 + component_scores.io_efficiency * weights.io_weight
259 + component_scores.network_efficiency * weights.network_weight;
260
261 weighted_score.clamp(0.0, 1.0)
262 }
263
264 fn default_weights_for_task_type(
266 task_type: &crate::capture::backends::task_profile::TaskType,
267 ) -> EfficiencyWeights {
268 match task_type {
269 crate::capture::backends::task_profile::TaskType::CpuIntensive => EfficiencyWeights {
270 cpu_weight: 0.6,
271 memory_weight: 0.2,
272 io_weight: 0.1,
273 network_weight: 0.1,
274 },
275 crate::capture::backends::task_profile::TaskType::IoIntensive => EfficiencyWeights {
276 cpu_weight: 0.2,
277 memory_weight: 0.1,
278 io_weight: 0.6,
279 network_weight: 0.1,
280 },
281 crate::capture::backends::task_profile::TaskType::NetworkIntensive => {
282 EfficiencyWeights {
283 cpu_weight: 0.2,
284 memory_weight: 0.1,
285 io_weight: 0.1,
286 network_weight: 0.6,
287 }
288 }
289 crate::capture::backends::task_profile::TaskType::MemoryIntensive => {
290 EfficiencyWeights {
291 cpu_weight: 0.2,
292 memory_weight: 0.6,
293 io_weight: 0.1,
294 network_weight: 0.1,
295 }
296 }
297 crate::capture::backends::task_profile::TaskType::GpuCompute => EfficiencyWeights {
298 cpu_weight: 0.5,
299 memory_weight: 0.2,
300 io_weight: 0.1,
301 network_weight: 0.2,
302 },
303 _ => EfficiencyWeights::default(),
304 }
305 }
306}
307
308impl Default for EfficiencyScorer {
309 fn default() -> Self {
310 Self::new()
311 }
312}
313
314#[cfg(test)]
315mod tests {
316 use super::*;
317
318 #[test]
319 fn test_efficiency_config_default() {
320 let config = EfficiencyConfig::default();
321 assert!(config.enable_cpu_efficiency);
322 assert!(config.enable_memory_efficiency);
323 assert!(config.enable_io_efficiency);
324 assert!(config.enable_network_efficiency);
325 }
326
327 #[test]
328 fn test_efficiency_config_minimal() {
329 let config = EfficiencyConfig::minimal();
330 assert!(config.enable_cpu_efficiency);
331 assert!(config.enable_memory_efficiency);
332 assert!(!config.enable_io_efficiency);
333 assert!(!config.enable_network_efficiency);
334 }
335
336 #[test]
337 fn test_task_type_weights_default() {
338 let weights = EfficiencyWeights::default();
339 assert_eq!(weights.cpu_weight, 0.25);
340 assert_eq!(weights.memory_weight, 0.25);
341 assert_eq!(weights.io_weight, 0.25);
342 assert_eq!(weights.network_weight, 0.25);
343 }
344
345 #[test]
346 fn test_component_scores_default() {
347 let scores = ComponentScores::default();
348 assert_eq!(scores.cpu_efficiency, 0.0);
349 assert_eq!(scores.memory_efficiency, 0.0);
350 assert_eq!(scores.io_efficiency, 0.0);
351 assert_eq!(scores.network_efficiency, 0.0);
352 }
353
354 #[test]
355 fn test_component_scores_overall() {
356 let scores = ComponentScores {
357 cpu_efficiency: 0.8,
358 memory_efficiency: 0.6,
359 io_efficiency: 0.4,
360 network_efficiency: 0.2,
361 };
362
363 let overall = scores.overall();
364 assert!(
365 (overall - 0.5).abs() < f64::EPSILON,
366 "Expected overall score to be 0.5, got {}",
367 overall
368 );
369 }
370
371 #[test]
372 fn test_cpu_efficiency_calculation() {
373 let scorer = EfficiencyScorer::new();
374
375 let efficiency = scorer.calculate_cpu_efficiency(0.0);
376 assert_eq!(efficiency, 0.0);
377
378 let efficiency = scorer.calculate_cpu_efficiency(50.0);
379 assert_eq!(efficiency, 1.0);
380
381 let efficiency = scorer.calculate_cpu_efficiency(100.0);
382 assert_eq!(efficiency, 1.0);
383 }
384
385 #[test]
386 fn test_memory_efficiency_calculation() {
387 let scorer = EfficiencyScorer::new();
388
389 let mut profile = crate::capture::backends::task_profile::TaskMemoryProfile::new(
390 1,
391 "test".to_string(),
392 crate::capture::backends::task_profile::TaskType::default(),
393 );
394
395 let efficiency = scorer.calculate_memory_efficiency(&profile);
396 assert_eq!(efficiency, 1.0);
397
398 profile.total_bytes = 1000;
399 profile.current_memory = 500;
400 let efficiency = scorer.calculate_memory_efficiency(&profile);
401 assert_eq!(efficiency, 0.5);
402 }
403
404 #[test]
405 fn test_io_efficiency_calculation() {
406 let scorer = EfficiencyScorer::new();
407
408 let efficiency = scorer.calculate_io_efficiency(0);
409 assert_eq!(efficiency, 0.0);
410
411 let efficiency = scorer.calculate_io_efficiency(65536);
412 assert_eq!(efficiency, 1.0);
413 }
414
415 #[test]
416 fn test_network_efficiency_calculation() {
417 let scorer = EfficiencyScorer::new();
418
419 let efficiency = scorer.calculate_network_efficiency(0);
420 assert_eq!(efficiency, 0.0);
421
422 let efficiency = scorer.calculate_network_efficiency(1_048_576); assert!((efficiency - 1.0).abs() < f64::EPSILON);
424 }
425
426 #[test]
427 fn test_weighted_efficiency_cpu_intensive() {
428 let scorer = EfficiencyScorer::new();
429
430 let task_type = crate::capture::backends::task_profile::TaskType::CpuIntensive;
431 let component_scores = ComponentScores {
432 cpu_efficiency: 0.8,
433 memory_efficiency: 0.6,
434 io_efficiency: 0.4,
435 network_efficiency: 0.2,
436 };
437
438 let weighted = scorer.calculate_weighted_efficiency(&task_type, &component_scores);
439 assert!((weighted - 0.66).abs() < f64::EPSILON);
440 }
441
442 #[test]
443 fn test_weighted_efficiency_io_intensive() {
444 let scorer = EfficiencyScorer::new();
445
446 let task_type = crate::capture::backends::task_profile::TaskType::IoIntensive;
447 let component_scores = ComponentScores {
448 cpu_efficiency: 0.6,
449 memory_efficiency: 0.4,
450 io_efficiency: 0.8,
451 network_efficiency: 0.2,
452 };
453
454 let weighted = scorer.calculate_weighted_efficiency(&task_type, &component_scores);
455 assert!((weighted - 0.66).abs() < f64::EPSILON);
458 }
459
460 #[test]
461 fn test_weighted_efficiency_memory_intensive() {
462 let scorer = EfficiencyScorer::new();
463
464 let task_type = crate::capture::backends::task_profile::TaskType::MemoryIntensive;
465 let component_scores = ComponentScores {
466 cpu_efficiency: 0.6,
467 memory_efficiency: 0.8,
468 io_efficiency: 0.4,
469 network_efficiency: 0.2,
470 };
471
472 let weighted = scorer.calculate_weighted_efficiency(&task_type, &component_scores);
473 assert!((weighted - 0.66).abs() < f64::EPSILON);
476 }
477
478 #[test]
479 fn test_weighted_efficiency_network_intensive() {
480 let scorer = EfficiencyScorer::new();
481
482 let task_type = crate::capture::backends::task_profile::TaskType::NetworkIntensive;
483 let component_scores = ComponentScores {
484 cpu_efficiency: 0.6,
485 memory_efficiency: 0.4,
486 io_efficiency: 0.2,
487 network_efficiency: 0.8,
488 };
489
490 let weighted = scorer.calculate_weighted_efficiency(&task_type, &component_scores);
491 assert!((weighted - 0.66).abs() < f64::EPSILON);
494 }
495}