1use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8
9use super::allocation::AllocationInfo;
10use super::scope::ScopeLifecycleMetrics;
11
12#[derive(Debug, Clone, Default, Serialize)]
17pub struct MemoryStats {
18 pub total_allocations: usize,
20 pub total_allocated: usize,
22 pub active_allocations: usize,
24 pub active_memory: usize,
26 pub peak_allocations: usize,
28 pub peak_memory: usize,
30 pub total_deallocations: usize,
32 pub total_deallocated: usize,
34 pub leaked_allocations: usize,
36 pub leaked_memory: usize,
38 pub fragmentation_analysis: FragmentationAnalysis,
40 pub lifecycle_stats: ScopeLifecycleMetrics,
42 pub allocations: Vec<AllocationInfo>,
44 pub system_library_stats: SystemLibraryStats,
46 pub concurrency_analysis: ConcurrencyAnalysis,
48}
49
50impl MemoryStats {
51 pub fn new() -> Self {
53 Self {
54 total_allocations: 0,
55 total_allocated: 0,
56 active_allocations: 0,
57 active_memory: 0,
58 peak_allocations: 0,
59 peak_memory: 0,
60 total_deallocations: 0,
61 total_deallocated: 0,
62 leaked_allocations: 0,
63 leaked_memory: 0,
64 fragmentation_analysis: FragmentationAnalysis::default(),
65 lifecycle_stats: ScopeLifecycleMetrics::default(),
66 allocations: Vec::new(),
67 system_library_stats: SystemLibraryStats::default(),
68 concurrency_analysis: ConcurrencyAnalysis::default(),
69 }
70 }
71}
72
73impl From<crate::core::types::MemoryStats> for MemoryStats {
74 fn from(old: crate::core::types::MemoryStats) -> Self {
75 Self {
76 total_allocations: old.total_allocations,
77 total_allocated: old.total_allocated,
78 active_allocations: old.active_allocations,
79 active_memory: old.active_memory,
80 peak_allocations: old.peak_allocations,
81 peak_memory: old.peak_memory,
82 total_deallocations: old.total_deallocations,
83 total_deallocated: old.total_deallocated,
84 leaked_allocations: old.leaked_allocations,
85 leaked_memory: old.leaked_memory,
86 fragmentation_analysis: FragmentationAnalysis {
88 fragmentation_ratio: old.fragmentation_analysis.fragmentation_ratio,
89 largest_free_block: old.fragmentation_analysis.largest_free_block,
90 smallest_free_block: old.fragmentation_analysis.smallest_free_block,
91 free_block_count: old.fragmentation_analysis.free_block_count,
92 total_free_memory: old.fragmentation_analysis.total_free_memory,
93 external_fragmentation: old.fragmentation_analysis.external_fragmentation,
94 internal_fragmentation: old.fragmentation_analysis.internal_fragmentation,
95 },
96 lifecycle_stats: ScopeLifecycleMetrics::default(),
98 allocations: old.allocations.into_iter().map(|a| a.into()).collect(),
99 system_library_stats: SystemLibraryStats::default(),
100 concurrency_analysis: ConcurrencyAnalysis::default(),
101 }
102 }
103}
104
105#[derive(Debug, Clone, Serialize)]
107pub struct MemoryTypeInfo {
108 pub type_name: String,
110 pub total_size: usize,
112 pub allocation_count: usize,
114 pub average_size: usize,
116 pub largest_allocation: usize,
118 pub smallest_allocation: usize,
120 pub active_instances: usize,
122 pub leaked_instances: usize,
124}
125
126#[derive(Debug, Clone, Serialize)]
128pub struct TypeMemoryUsage {
129 pub type_name: String,
131 pub total_size: usize,
133 pub allocation_count: usize,
135 pub average_size: f64,
137 pub peak_size: usize,
139 pub current_size: usize,
141 pub efficiency_score: f64,
143}
144
145#[derive(Debug, Clone, Default, Serialize, Deserialize)]
147pub struct FragmentationAnalysis {
148 pub fragmentation_ratio: f64,
150 pub largest_free_block: usize,
152 pub smallest_free_block: usize,
154 pub free_block_count: usize,
156 pub total_free_memory: usize,
158 pub external_fragmentation: f64,
160 pub internal_fragmentation: f64,
162}
163
164#[derive(Debug, Clone, Default, Serialize)]
166pub struct SystemLibraryStats {
167 pub std_collections: LibraryUsage,
169 pub async_runtime: LibraryUsage,
171 pub network_io: LibraryUsage,
173 pub file_system: LibraryUsage,
175 pub serialization: LibraryUsage,
177 pub regex_engine: LibraryUsage,
179 pub crypto_security: LibraryUsage,
181 pub database: LibraryUsage,
183 pub graphics_ui: LibraryUsage,
185 pub http_stack: LibraryUsage,
187}
188
189#[derive(Debug, Clone, Default, Serialize)]
191pub struct LibraryUsage {
192 pub allocation_count: usize,
194 pub total_bytes: usize,
196 pub peak_bytes: usize,
198 pub average_size: f64,
200 pub categories: HashMap<String, usize>,
202 pub hotspot_functions: Vec<String>,
204}
205
206#[derive(Debug, Clone, Default, Serialize)]
208pub struct ConcurrencyAnalysis {
209 pub thread_safety_allocations: usize,
211 pub shared_memory_bytes: usize,
213 pub mutex_protected: usize,
215 pub arc_shared: usize,
217 pub rc_shared: usize,
219 pub channel_buffers: usize,
221 pub thread_local_storage: usize,
223 pub atomic_operations: usize,
225 pub lock_contention_risk: String,
227}
228
229#[cfg(test)]
230mod tests {
231 use super::*;
232
233 #[test]
234 fn test_memory_stats_creation() {
235 let stats = MemoryStats::new();
236
237 assert_eq!(stats.total_allocations, 0);
238 assert_eq!(stats.total_allocated, 0);
239 assert_eq!(stats.active_allocations, 0);
240 }
241
242 #[test]
243 fn test_fragmentation_analysis_default() {
244 let frag = FragmentationAnalysis::default();
245
246 assert_eq!(frag.fragmentation_ratio, 0.0);
247 assert_eq!(frag.largest_free_block, 0);
248 assert_eq!(frag.free_block_count, 0);
249 }
250
251 #[test]
252 fn test_system_library_stats_default() {
253 let stats = SystemLibraryStats::default();
254
255 assert_eq!(stats.std_collections.allocation_count, 0);
256 assert_eq!(stats.async_runtime.total_bytes, 0);
257 assert_eq!(stats.network_io.peak_bytes, 0);
258 }
259
260 #[test]
261 fn test_library_usage_default() {
262 let usage = LibraryUsage::default();
263
264 assert_eq!(usage.allocation_count, 0);
265 assert_eq!(usage.total_bytes, 0);
266 assert_eq!(usage.average_size, 0.0);
267 assert!(usage.categories.is_empty());
268 assert!(usage.hotspot_functions.is_empty());
269 }
270
271 #[test]
272 fn test_concurrency_analysis_default() {
273 let analysis = ConcurrencyAnalysis::default();
274
275 assert_eq!(analysis.thread_safety_allocations, 0);
276 assert_eq!(analysis.shared_memory_bytes, 0);
277 assert_eq!(analysis.mutex_protected, 0);
278 }
279
280 #[test]
281 fn test_memory_stats_default() {
282 let stats = MemoryStats::default();
283
284 assert_eq!(stats.total_allocations, 0);
285 assert_eq!(stats.active_memory, 0);
286 assert_eq!(stats.peak_memory, 0);
287 assert_eq!(stats.leaked_allocations, 0);
288 }
289
290 #[test]
291 fn test_memory_stats_with_values() {
292 let mut stats = MemoryStats::new();
293 stats.total_allocations = 100;
294 stats.total_allocated = 1024 * 1024;
295 stats.active_allocations = 50;
296 stats.active_memory = 512 * 1024;
297 stats.peak_allocations = 75;
298 stats.peak_memory = 768 * 1024;
299 stats.total_deallocations = 50;
300 stats.total_deallocated = 512 * 1024;
301 stats.leaked_allocations = 5;
302 stats.leaked_memory = 10240;
303
304 assert_eq!(stats.total_allocations, 100);
305 assert_eq!(stats.active_allocations, 50);
306 assert_eq!(stats.leaked_allocations, 5);
307 }
308
309 #[test]
310 fn test_fragmentation_analysis_with_values() {
311 let frag = FragmentationAnalysis {
312 fragmentation_ratio: 0.35,
313 largest_free_block: 65536,
314 smallest_free_block: 16,
315 free_block_count: 128,
316 total_free_memory: 524288,
317 external_fragmentation: 0.25,
318 internal_fragmentation: 0.10,
319 };
320
321 assert!((frag.fragmentation_ratio - 0.35).abs() < f64::EPSILON);
322 assert_eq!(frag.free_block_count, 128);
323 assert!((frag.external_fragmentation - 0.25).abs() < f64::EPSILON);
324 }
325
326 #[test]
327 fn test_memory_type_info_creation() {
328 let info = MemoryTypeInfo {
329 type_name: "Vec<u8>".to_string(),
330 total_size: 1024,
331 allocation_count: 10,
332 average_size: 102,
333 largest_allocation: 512,
334 smallest_allocation: 16,
335 active_instances: 8,
336 leaked_instances: 1,
337 };
338
339 assert_eq!(info.type_name, "Vec<u8>");
340 assert_eq!(info.allocation_count, 10);
341 assert_eq!(info.leaked_instances, 1);
342 }
343
344 #[test]
345 fn test_type_memory_usage_creation() {
346 let usage = TypeMemoryUsage {
347 type_name: "String".to_string(),
348 total_size: 2048,
349 allocation_count: 20,
350 average_size: 102.4,
351 peak_size: 512,
352 current_size: 256,
353 efficiency_score: 0.85,
354 };
355
356 assert_eq!(usage.type_name, "String");
357 assert!((usage.average_size - 102.4).abs() < f64::EPSILON);
358 assert!((usage.efficiency_score - 0.85).abs() < f64::EPSILON);
359 }
360
361 #[test]
362 fn test_library_usage_with_values() {
363 let mut categories = HashMap::new();
364 categories.insert("HashMap".to_string(), 1000);
365 categories.insert("Vec".to_string(), 2000);
366
367 let usage = LibraryUsage {
368 allocation_count: 100,
369 total_bytes: 10240,
370 peak_bytes: 5120,
371 average_size: 102.4,
372 categories,
373 hotspot_functions: vec!["push".to_string(), "insert".to_string()],
374 };
375
376 assert_eq!(usage.allocation_count, 100);
377 assert_eq!(usage.categories.len(), 2);
378 assert_eq!(usage.hotspot_functions.len(), 2);
379 }
380
381 #[test]
382 fn test_system_library_stats_with_values() {
383 let mut stats = SystemLibraryStats::default();
384 stats.std_collections.allocation_count = 500;
385 stats.async_runtime.total_bytes = 10240;
386 stats.network_io.peak_bytes = 2048;
387 stats.file_system.allocation_count = 100;
388 stats.serialization.total_bytes = 4096;
389 stats.regex_engine.allocation_count = 50;
390 stats.crypto_security.total_bytes = 8192;
391 stats.database.allocation_count = 200;
392 stats.graphics_ui.total_bytes = 16384;
393 stats.http_stack.allocation_count = 75;
394
395 assert_eq!(stats.std_collections.allocation_count, 500);
396 assert_eq!(stats.async_runtime.total_bytes, 10240);
397 }
398
399 #[test]
400 fn test_concurrency_analysis_with_values() {
401 let analysis = ConcurrencyAnalysis {
402 thread_safety_allocations: 100,
403 shared_memory_bytes: 10240,
404 mutex_protected: 50,
405 arc_shared: 30,
406 rc_shared: 20,
407 channel_buffers: 15,
408 thread_local_storage: 10,
409 atomic_operations: 200,
410 lock_contention_risk: "Low".to_string(),
411 };
412
413 assert_eq!(analysis.thread_safety_allocations, 100);
414 assert_eq!(analysis.arc_shared, 30);
415 assert_eq!(analysis.lock_contention_risk, "Low");
416 }
417
418 #[test]
419 fn test_memory_stats_serialization() {
420 let stats = MemoryStats::new();
421
422 let json = serde_json::to_string(&stats).unwrap();
423 assert!(json.contains("total_allocations"));
424 assert!(json.contains("active_memory"));
425 }
426
427 #[test]
428 fn test_fragmentation_analysis_serialization() {
429 let frag = FragmentationAnalysis {
430 fragmentation_ratio: 0.5,
431 largest_free_block: 1024,
432 smallest_free_block: 16,
433 free_block_count: 50,
434 total_free_memory: 2048,
435 external_fragmentation: 0.3,
436 internal_fragmentation: 0.2,
437 };
438
439 let json = serde_json::to_string(&frag).unwrap();
440 let deserialized: FragmentationAnalysis = serde_json::from_str(&json).unwrap();
441 assert!((deserialized.fragmentation_ratio - frag.fragmentation_ratio).abs() < f64::EPSILON);
442 }
443
444 #[test]
445 fn test_memory_type_info_serialization() {
446 let info = MemoryTypeInfo {
447 type_name: "HashMap<String, i32>".to_string(),
448 total_size: 4096,
449 allocation_count: 25,
450 average_size: 163,
451 largest_allocation: 1024,
452 smallest_allocation: 64,
453 active_instances: 20,
454 leaked_instances: 2,
455 };
456
457 let json = serde_json::to_string(&info).unwrap();
458 assert!(json.contains("HashMap"));
459 assert!(json.contains("4096"));
460 }
461
462 #[test]
463 fn test_type_memory_usage_serialization() {
464 let usage = TypeMemoryUsage {
465 type_name: "Box<dyn Any>".to_string(),
466 total_size: 8192,
467 allocation_count: 100,
468 average_size: 81.92,
469 peak_size: 2048,
470 current_size: 1024,
471 efficiency_score: 0.75,
472 };
473
474 let json = serde_json::to_string(&usage).unwrap();
475 assert!(json.contains("Box"));
476 assert!(json.contains("8192"));
477 }
478
479 #[test]
480 fn test_library_usage_serialization() {
481 let usage = LibraryUsage {
482 allocation_count: 50,
483 total_bytes: 5120,
484 peak_bytes: 2560,
485 average_size: 102.4,
486 categories: HashMap::new(),
487 hotspot_functions: vec![],
488 };
489
490 let json = serde_json::to_string(&usage).unwrap();
491 assert!(json.contains("allocation_count"));
492 }
493
494 #[test]
495 fn test_concurrency_analysis_serialization() {
496 let analysis = ConcurrencyAnalysis {
497 thread_safety_allocations: 10,
498 shared_memory_bytes: 1024,
499 mutex_protected: 5,
500 arc_shared: 3,
501 rc_shared: 2,
502 channel_buffers: 1,
503 thread_local_storage: 0,
504 atomic_operations: 50,
505 lock_contention_risk: "Medium".to_string(),
506 };
507
508 let json = serde_json::to_string(&analysis).unwrap();
509 assert!(json.contains("thread_safety_allocations"));
510 }
511
512 #[test]
513 fn test_boundary_values_memory_stats() {
514 let mut stats = MemoryStats::new();
515 stats.total_allocations = usize::MAX;
516 stats.total_allocated = usize::MAX;
517 stats.active_allocations = usize::MAX;
518 stats.active_memory = usize::MAX;
519 stats.peak_allocations = usize::MAX;
520 stats.peak_memory = usize::MAX;
521
522 assert_eq!(stats.total_allocations, usize::MAX);
523 assert_eq!(stats.peak_memory, usize::MAX);
524 }
525
526 #[test]
527 fn test_boundary_values_fragmentation() {
528 let frag = FragmentationAnalysis {
529 fragmentation_ratio: f64::MAX,
530 largest_free_block: usize::MAX,
531 smallest_free_block: usize::MAX,
532 free_block_count: usize::MAX,
533 total_free_memory: usize::MAX,
534 external_fragmentation: f64::MAX,
535 internal_fragmentation: f64::MAX,
536 };
537
538 assert!(frag.fragmentation_ratio.is_finite());
539 assert_eq!(frag.largest_free_block, usize::MAX);
540 }
541
542 #[test]
543 fn test_boundary_values_concurrency() {
544 let analysis = ConcurrencyAnalysis {
545 thread_safety_allocations: usize::MAX,
546 shared_memory_bytes: usize::MAX,
547 mutex_protected: usize::MAX,
548 arc_shared: usize::MAX,
549 rc_shared: usize::MAX,
550 channel_buffers: usize::MAX,
551 thread_local_storage: usize::MAX,
552 atomic_operations: usize::MAX,
553 lock_contention_risk: String::new(),
554 };
555
556 assert_eq!(analysis.thread_safety_allocations, usize::MAX);
557 assert_eq!(analysis.atomic_operations, usize::MAX);
558 }
559
560 #[test]
561 fn test_memory_stats_clone() {
562 let mut stats = MemoryStats::new();
563 stats.total_allocations = 42;
564
565 let cloned = stats.clone();
566 assert_eq!(cloned.total_allocations, 42);
567 }
568
569 #[test]
570 fn test_memory_stats_debug() {
571 let stats = MemoryStats::new();
572 let debug_str = format!("{:?}", stats);
573
574 assert!(debug_str.contains("MemoryStats"));
575 assert!(debug_str.contains("total_allocations"));
576 }
577
578 #[test]
579 fn test_fragmentation_analysis_clone() {
580 let frag = FragmentationAnalysis {
581 fragmentation_ratio: 0.75,
582 largest_free_block: 2048,
583 smallest_free_block: 32,
584 free_block_count: 100,
585 total_free_memory: 4096,
586 external_fragmentation: 0.5,
587 internal_fragmentation: 0.25,
588 };
589
590 let cloned = frag.clone();
591 assert!((cloned.fragmentation_ratio - 0.75).abs() < f64::EPSILON);
592 }
593
594 #[test]
595 fn test_library_usage_clone() {
596 let usage = LibraryUsage {
597 allocation_count: 25,
598 total_bytes: 2560,
599 peak_bytes: 1280,
600 average_size: 102.4,
601 categories: HashMap::new(),
602 hotspot_functions: vec!["test".to_string()],
603 };
604
605 let cloned = usage.clone();
606 assert_eq!(cloned.allocation_count, 25);
607 }
608
609 #[test]
610 fn test_concurrency_analysis_clone() {
611 let analysis = ConcurrencyAnalysis {
612 thread_safety_allocations: 100,
613 shared_memory_bytes: 2048,
614 mutex_protected: 50,
615 arc_shared: 25,
616 rc_shared: 15,
617 channel_buffers: 10,
618 thread_local_storage: 5,
619 atomic_operations: 200,
620 lock_contention_risk: "High".to_string(),
621 };
622
623 let cloned = analysis.clone();
624 assert_eq!(cloned.thread_safety_allocations, 100);
625 }
626
627 #[test]
628 fn test_empty_library_usage_categories() {
629 let usage = LibraryUsage::default();
630 assert!(usage.categories.is_empty());
631 assert!(usage.hotspot_functions.is_empty());
632 }
633
634 #[test]
635 fn test_library_usage_with_categories() {
636 let mut categories = HashMap::new();
637 categories.insert("String".to_string(), 500);
638 categories.insert("Vec".to_string(), 1000);
639
640 let usage = LibraryUsage {
641 allocation_count: 10,
642 total_bytes: 1500,
643 peak_bytes: 750,
644 average_size: 150.0,
645 categories,
646 hotspot_functions: vec![],
647 };
648
649 assert_eq!(usage.categories.get("String"), Some(&500));
650 assert_eq!(usage.categories.get("Vec"), Some(&1000));
651 assert_eq!(usage.categories.get("HashMap"), None);
652 }
653}