Skip to main content

buddy_slab_allocator/buddy/
stats.rs

1//! Statistics and debugging for buddy allocator
2//!
3//! Provides detailed statistics tracking and failure reporting.
4
5use super::buddy_block::ZoneInfo;
6
7/// Maximum order supported
8pub const DEFAULT_MAX_ORDER: usize = 28;
9
10/// Buddy system statistics
11#[derive(Debug, Clone, Copy)]
12pub struct BuddyStats {
13    pub total_pages: usize,
14    pub free_pages: usize,
15    pub used_pages: usize,
16    pub free_pages_by_order: [usize; DEFAULT_MAX_ORDER + 1],
17}
18
19impl Default for BuddyStats {
20    fn default() -> Self {
21        Self {
22            total_pages: 0,
23            free_pages: 0,
24            used_pages: 0,
25            free_pages_by_order: [0; DEFAULT_MAX_ORDER + 1],
26        }
27    }
28}
29
30impl BuddyStats {
31    pub const fn new() -> Self {
32        Self {
33            total_pages: 0,
34            free_pages: 0,
35            used_pages: 0,
36            free_pages_by_order: [0; DEFAULT_MAX_ORDER + 1],
37        }
38    }
39
40    /// Add statistics from another BuddyStats
41    pub fn add(&mut self, other: &BuddyStats) {
42        self.total_pages += other.total_pages;
43        self.free_pages += other.free_pages;
44        self.used_pages += other.used_pages;
45        for (i, &count) in other.free_pages_by_order.iter().enumerate() {
46            self.free_pages_by_order[i] += count;
47        }
48    }
49}
50
51/// Detailed memory statistics reporter
52pub struct MemoryStatsReporter;
53
54impl MemoryStatsReporter {
55    /// Print detailed allocation failure statistics
56    /// This is a standalone function to keep allocation logic clean
57    #[allow(unused_variables)]
58    pub fn print_alloc_failure_stats(
59        page_size: usize,
60        num_zones: usize,
61        total_stats: &BuddyStats,
62        zone_infos: &[ZoneInfo],
63        zone_stats: &[BuddyStats],
64        request_pages: usize,
65        request_align: usize,
66    ) {
67        {
68            #[cfg(feature = "log")]
69            use log::error;
70            error!("========================================");
71            error!(
72                "Request: {} pages ({} KB, alignment:{})",
73                request_pages,
74                (request_pages * page_size) / (1024),
75                request_align
76            );
77
78            error!("Overall Memory State:");
79            error!("  Total zones: {num_zones}");
80            error!(
81                "  Total pages: {} ({} KB)",
82                total_stats.total_pages,
83                (total_stats.total_pages * page_size) / 1024
84            );
85            error!(
86                "  Free pages: {} ({} KB)",
87                total_stats.free_pages,
88                (total_stats.free_pages * page_size) / (1024)
89            );
90            error!(
91                "  Used pages: {} ({} KB)",
92                total_stats.used_pages,
93                (total_stats.used_pages * page_size) / (1024)
94            );
95            error!("========================================");
96
97            for (i, zone_info) in zone_infos.iter().take(num_zones).enumerate() {
98                error!("Zone {i}:");
99                error!(
100                    "  Range: [{:#x}, {:#x})",
101                    zone_info.start_addr, zone_info.end_addr
102                );
103                error!("  Total pages: {}", zone_info.total_pages);
104                error!(
105                    "  Free pages: {} / {}",
106                    zone_stats[i].free_pages, zone_info.total_pages
107                );
108                error!("  Free blocks by order:");
109
110                for order in (0..=DEFAULT_MAX_ORDER).rev() {
111                    let count = zone_stats[i].free_pages_by_order[order];
112                    if count > 0 {
113                        let block_size = (1 << order) * page_size;
114                        let total_kb = (count * block_size) / (1024);
115                        error!(
116                            "    Order {}: {} blocks ({} KB each, {} KB total)",
117                            order,
118                            count,
119                            block_size / (1024),
120                            total_kb
121                        );
122                    }
123                }
124                error!("----------------------------------------");
125            }
126
127            error!("========================================");
128        }
129    }
130}