From 9da8998cd46b1f47c637471bc03471e2aeeab310 Mon Sep 17 00:00:00 2001 From: Levente Kurusa Date: Sun, 16 Sep 2018 16:05:29 +0200 Subject: [PATCH] memory: parse numa_stat field Signed-off-by: Levente Kurusa --- src/memory.rs | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/src/memory.rs b/src/memory.rs index 0a15379..458d328 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -20,6 +20,101 @@ pub struct MemController{ path: PathBuf, } +/// Contains statistics about the NUMA locality of the control group's tasks. +#[derive(Debug, PartialEq, Eq)] +pub struct NumaStat { + /// Total amount of pages used by the control group. + pub total_pages: u64, + /// Total amount of pages used by the control group, broken down by NUMA node. + pub total_pages_per_node: Vec, + /// Total amount of file pages used by the control group. + pub file_pages: u64, + /// Total amount of file pages used by the control group, broken down by NUMA node. + pub file_pages_per_node: Vec, + /// Total amount of anonymous pages used by the control group. + pub anon_pages: u64, + /// Total amount of anonymous pages used by the control group, broken down by NUMA node. + pub anon_pages_per_node: Vec, + /// Total amount of unevictable pages used by the control group. + pub unevictable_pages: u64, + /// Total amount of unevictable pages used by the control group, broken down by NUMA node. + pub unevictable_pages_per_node: Vec, + + /// Same as `total_pages`, but includes the descedant control groups' number as well. + pub hierarchical_total_pages: u64, + /// Same as `total_pages_per_node`, but includes the descedant control groups' number as well. + pub hierarchical_total_pages_per_node: Vec, + /// Same as `file_pages`, but includes the descedant control groups' number as well. + pub hierarchical_file_pages: u64, + /// Same as `file_pages_per_node`, but includes the descedant control groups' number as well. + pub hierarchical_file_pages_per_node: Vec, + /// Same as `anon_pages`, but includes the descedant control groups' number as well. + pub hierarchical_anon_pages: u64, + /// Same as `anon_pages_per_node`, but includes the descedant control groups' number as well. + pub hierarchical_anon_pages_per_node: Vec, + /// Same as `unevictable`, but includes the descedant control groups' number as well. + pub hierarchical_unevictable_pages: u64, + /// Same as `unevictable_per_node`, but includes the descedant control groups' number as well. + pub hierarchical_unevictable_pages_per_node: Vec, +} + +fn parse_numa_stat(s: String) -> Result { + // Parse the number of nodes + let nodes = (s.split_whitespace().collect::>().len() - 8) / 8; + let mut ls = s.lines(); + let total_line = ls.next().unwrap(); + let file_line = ls.next().unwrap(); + let anon_line = ls.next().unwrap(); + let unevict_line = ls.next().unwrap(); + let hier_total_line = ls.next().unwrap(); + let hier_file_line = ls.next().unwrap(); + let hier_anon_line = ls.next().unwrap(); + let hier_unevict_line = ls.next().unwrap(); + + Ok(NumaStat { + total_pages: total_line.split(|x| x == ' ' || x == '=').collect::>()[1].parse::().unwrap_or(0), + total_pages_per_node: { + let spl = &total_line.split(" ").collect::>()[1..]; + spl.iter().map(|x| x.split("=").collect::>()[1].parse::().unwrap_or(0)).collect() + }, + file_pages: file_line.split(|x| x == ' ' || x == '=').collect::>()[1].parse::().unwrap_or(0), + file_pages_per_node: { + let spl = &file_line.split(" ").collect::>()[1..]; + spl.iter().map(|x| x.split("=").collect::>()[1].parse::().unwrap_or(0)).collect() + }, + anon_pages: anon_line.split(|x| x == ' ' || x == '=').collect::>()[1].parse::().unwrap_or(0), + anon_pages_per_node: { + let spl = &anon_line.split(" ").collect::>()[1..]; + spl.iter().map(|x| x.split("=").collect::>()[1].parse::().unwrap_or(0)).collect() + }, + unevictable_pages: unevict_line.split(|x| x == ' ' || x == '=').collect::>()[1].parse::().unwrap_or(0), + unevictable_pages_per_node: { + let spl = &unevict_line.split(" ").collect::>()[1..]; + spl.iter().map(|x| x.split("=").collect::>()[1].parse::().unwrap_or(0)).collect() + }, + hierarchical_total_pages: hier_total_line.split(|x| x == ' ' || x == '=').collect::>()[1].parse::().unwrap_or(0), + hierarchical_total_pages_per_node: { + let spl = &hier_total_line.split(" ").collect::>()[1..]; + spl.iter().map(|x| x.split("=").collect::>()[1].parse::().unwrap_or(0)).collect() + }, + hierarchical_file_pages: hier_file_line.split(|x| x == ' ' || x == '=').collect::>()[1].parse::().unwrap_or(0), + hierarchical_file_pages_per_node: { + let spl = &hier_file_line.split(" ").collect::>()[1..]; + spl.iter().map(|x| x.split("=").collect::>()[1].parse::().unwrap_or(0)).collect() + }, + hierarchical_anon_pages: hier_anon_line.split(|x| x == ' ' || x == '=').collect::>()[1].parse::().unwrap_or(0), + hierarchical_anon_pages_per_node: { + let spl = &hier_anon_line.split(" ").collect::>()[1..]; + spl.iter().map(|x| x.split("=").collect::>()[1].parse::().unwrap_or(0)).collect() + }, + hierarchical_unevictable_pages: hier_unevict_line.split(|x| x == ' ' || x == '=').collect::>()[1].parse::().unwrap_or(0), + hierarchical_unevictable_pages_per_node: { + let spl = &hier_unevict_line.split(" ").collect::>()[1..]; + spl.iter().map(|x| x.split("=").collect::>()[1].parse::().unwrap_or(0)).collect() + }, + }) +} + /// Contains statistics about the current usage of memory and swap (together, not seperately) by /// the control group's tasks. #[derive(Debug)] @@ -316,3 +411,42 @@ fn read_string_from(mut file: File) -> Result { Err(e) => Err(CgroupError::ReadError(e)), } } + +#[cfg(test)] +mod tests { + use memory::{NumaStat, parse_numa_stat}; + const good_value: &str = "\ +total=51189 N0=51189 N1=123 +file=50175 N0=50175 N1=123 +anon=1014 N0=1014 N1=123 +unevictable=0 N0=0 N1=123 +hierarchical_total=1628573 N0=1628573 N1=123 +hierarchical_file=858151 N0=858151 N1=123 +hierarchical_anon=770402 N0=770402 N1=123 +hierarchical_unevictable=20 N0=20 N1=123 +"; + + #[test] + fn test_parse_numa_stat() { + assert_eq!(parse_numa_stat(good_value.to_string()), + Ok(NumaStat { + total_pages: 51189, + total_pages_per_node: vec![51189, 123], + file_pages: 50175, + file_pages_per_node: vec![50175, 123], + anon_pages: 1014, + anon_pages_per_node: vec![1014, 123], + unevictable_pages: 0, + unevictable_pages_per_node: vec![0, 123], + + hierarchical_total_pages: 1628573, + hierarchical_total_pages_per_node: vec![1628573, 123], + hierarchical_file_pages: 858151, + hierarchical_file_pages_per_node: vec![858151, 123], + hierarchical_anon_pages: 770402, + hierarchical_anon_pages_per_node: vec![770402, 123], + hierarchical_unevictable_pages: 20, + hierarchical_unevictable_pages_per_node: vec![20, 123], + })); + } +}