1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
//! > ### 5.2.2. `/proc/buddyinfo` //! > //! > <a id="idm139745916909296" class="indexterm" href=""></a> //! > //! > This file is used primarily for diagnosing memory fragmentation issues. //! > Using the buddy algorithm, each column represents the number of pages of a certain order (a certain size) that are available at any given time. //! > For example, for zone DMA (direct memory access), there are 90 of 2^(0*PAGE_SIZE) chunks of memory. //! > Similarly, there are 6 of 2^(1*PAGE_SIZE) chunks, and 2 of 2^(2*PAGE_SIZE) chunks of memory available. //! > //! > The `DMA` row references the first 16 MB on a system, the `HighMem` row references all memory greater than 4 GB on a system, and the `Normal` row references all memory in between. //! > //! > -- https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/5/html/deployment_guide/s1-proc-topfiles#s2-proc-buddyinfo //! > //! > //! > //! > //! > Node 0, zone DMA 0 4 5 4 4 3 ... //! > Node 0, zone Normal 1 0 0 1 101 8 ... //! > Node 0, zone HighMem 2 0 0 1 1 0 ... //! > //! > External fragmentation is a problem under some workloads, and buddyinfo is a //! > useful tool for helping diagnose these problems. Buddyinfo will give you a //! > clue as to how big an area you can safely allocate, or why a previous //! > allocation failed. //! > //! > Each column represents the number of pages of a certain order which are //! > available. In this case, there are 0 chunks of 2^0*PAGE_SIZE available in //! > ZONE_DMA, 4 chunks of 2^1*PAGE_SIZE in ZONE_DMA, 101 chunks of 2^4*PAGE_SIZE //! > available in ZONE_NORMAL, etc... //! > //! > More information relevant to external fragmentation can be found in pagetypeinfo. //! > //! > -- https://www.kernel.org/doc/Documentation/filesystems/proc.txt //! > //! > //! > //! > /proc/buddyinfo //! > This file contains information which is used for diagnosing memory fragmentation issues. //! > Each line starts with the identification of the node and the name of the zone which together identify a memory region //! > This is then followed by the count of available chunks of a certain order in which these zones are split. //! > The size in bytes of a certain order is given by the formula: //! > (2^order) * PAGE_SIZE //! //! > The binary buddy allocator algorithm inside the kernel will split one chunk into two chunks of a smaller order //! > (thus with half the size) or combine two contiguous chunks into one larger chunk of a higher order //! > (thus with double the size) to satisfy allocation requests and to counter memory fragmentation. //! > The order matches the column number, when starting to count at zero. //! > For example on an x86-64 system: //! > ```text //! > Node 0, zone DMA 1 1 1 0 2 1 1 0 1 1 3 //! > Node 0, zone DMA32 65 47 4 81 52 28 13 10 5 1 404 //! > Node 0, zone Normal 216 55 189 101 84 38 37 27 5 3 587 //! > ``` //! > //! > In this example, there is one node containing three zones and there are 11 different chunk sizes. //! > If the page size is 4 kilobytes, then the first zone called DMA (on x86 the first 16 megabyte of memory) //! > has 1 chunk of 4 kilobytes (order 0) available and has 3 chunks of 4 megabytes (order 10) available. //! > If the memory is heavily fragmented, the counters for higher order chunks will be zero //! > and allocation of large contiguous areas will fail. //! > Further information about the zones can be found in /proc/zoneinfo. //! > //! > -- https://manpages.debian.org/testing/manpages/procfs.5.en.html //! define_struct! { /// Represent the an entry of /proc/buddyinfo /// /// Reference to [`mm/vmstat.c`] /// (https://github.com/torvalds/linux/blob/89d57dddd7d319ded00415790a0bb3c954b7e386/mm/vmstat.c#L1356). pub struct BuddyInfo { node: i32, zone: String, free_areas: [u64;11], } } use std::str::FromStr; impl FromStr for BuddyInfo { type Err = crate::ProcErr; fn from_str(s: &str) -> Result<BuddyInfo, crate::ProcErr> { let columns: Vec<&str> = s.split_ascii_whitespace().collect(); if columns.len() != 15 { return Err("no enough fields to parse a Page".into()) } let node = columns[1].trim_end_matches(',').parse::<i32>()?; let zone = columns[3].to_string(); let mut free_areas = [0;11]; for (fa, v) in free_areas.iter_mut().zip(columns[4..].iter()) { *fa = v.parse::<u64>()?; } Ok(BuddyInfo{ node, zone, free_areas }) } } list_impl! { buddyinfo, "/proc/buddyinfo", BuddyInfo, '\n', 0 } #[cfg(test)] mod test { use super::*; #[test] fn test_parse_page() { let source = "Node 0, zone DMA 7 3 11 11 6 1 4 4 3 0 0"; let correct = BuddyInfo { node: 0, zone: String::from("DMA"), free_areas: [7,3,11,11,6,1,4,4,3,0,0] }; assert_eq!(correct, source.parse::<BuddyInfo>().unwrap()); } }