@@ -38,6 +38,9 @@ pub struct SingleCgroupModel {
3838 pub pressure : Option < CgroupPressureModel > ,
3939 #[ queriable( subquery) ]
4040 pub cgroup_stat : Option < CgroupStatModel > ,
41+ #[ queriable( subquery) ]
42+ #[ queriable( preferred_name = mem_numa) ]
43+ pub memory_numa_stat : Option < BTreeMap < u32 , CgroupMemoryNumaModel > > ,
4144}
4245
4346/// A model that represents a cgroup subtree. Each instance is a node that uses
@@ -225,6 +228,24 @@ impl CgroupModel {
225228
226229 let cgroup_stat = sample. cgroup_stat . as_ref ( ) . map ( CgroupStatModel :: new) ;
227230
231+ let memory_numa_stat = {
232+ sample. memory_numa_stat . as_ref ( ) . map ( |end_numa_nodes| {
233+ let begin_numa_nodes = last_if_inode_matches. and_then ( |( s, d) | {
234+ s. memory_numa_stat
235+ . as_ref ( )
236+ . map ( |numa_nodes| ( numa_nodes, d) )
237+ } ) ;
238+ end_numa_nodes
239+ . iter ( )
240+ . map ( |( node_id, stat) | {
241+ let begin_numa_stat = begin_numa_nodes
242+ . and_then ( |( nodes, d) | nodes. get ( node_id) . map ( |stat| ( stat, d) ) ) ;
243+ ( * node_id, CgroupMemoryNumaModel :: new ( stat, begin_numa_stat) )
244+ } )
245+ . collect ( )
246+ } )
247+ } ;
248+
228249 // recursively calculate view of children
229250 // `children` is optional, but we treat it the same as an empty map
230251 let empty = BTreeMap :: new ( ) ;
@@ -262,6 +283,7 @@ impl CgroupModel {
262283 pressure,
263284 depth,
264285 cgroup_stat,
286+ memory_numa_stat,
265287 } ,
266288 children,
267289 count : nr_descendants + 1 ,
@@ -653,6 +675,119 @@ impl CgroupPressureModel {
653675 }
654676 }
655677}
678+ #[ derive(
679+ Clone ,
680+ Debug ,
681+ Default ,
682+ PartialEq ,
683+ Serialize ,
684+ Deserialize ,
685+ below_derive:: Queriable
686+ ) ]
687+ pub struct CgroupMemoryNumaModel {
688+ pub total : Option < u64 > ,
689+ pub anon : Option < u64 > ,
690+ pub file : Option < u64 > ,
691+ pub kernel_stack : Option < u64 > ,
692+ pub pagetables : Option < u64 > ,
693+ pub shmem : Option < u64 > ,
694+ pub file_mapped : Option < u64 > ,
695+ pub file_dirty : Option < u64 > ,
696+ pub file_writeback : Option < u64 > ,
697+ pub swapcached : Option < u64 > ,
698+ pub anon_thp : Option < u64 > ,
699+ pub file_thp : Option < u64 > ,
700+ pub shmem_thp : Option < u64 > ,
701+ pub inactive_anon : Option < u64 > ,
702+ pub active_anon : Option < u64 > ,
703+ pub inactive_file : Option < u64 > ,
704+ pub active_file : Option < u64 > ,
705+ pub unevictable : Option < u64 > ,
706+ pub slab_reclaimable : Option < u64 > ,
707+ pub slab_unreclaimable : Option < u64 > ,
708+ pub workingset_refault_anon : Option < f64 > ,
709+ pub workingset_refault_file : Option < f64 > ,
710+ pub workingset_activate_anon : Option < f64 > ,
711+ pub workingset_activate_file : Option < f64 > ,
712+ pub workingset_restore_anon : Option < f64 > ,
713+ pub workingset_restore_file : Option < f64 > ,
714+ pub workingset_nodereclaim : Option < f64 > ,
715+ }
716+
717+ impl CgroupMemoryNumaModel {
718+ pub fn new (
719+ begin : & cgroupfs:: MemoryNumaStat ,
720+ last : Option < ( & cgroupfs:: MemoryNumaStat , Duration ) > ,
721+ ) -> CgroupMemoryNumaModel {
722+ let mut model = CgroupMemoryNumaModel {
723+ total : None ,
724+ anon : begin. anon ,
725+ file : begin. file ,
726+ kernel_stack : begin. kernel_stack ,
727+ pagetables : begin. pagetables ,
728+ shmem : begin. shmem ,
729+ file_mapped : begin. file_mapped ,
730+ file_dirty : begin. file_dirty ,
731+ file_writeback : begin. file_writeback ,
732+ swapcached : begin. swapcached ,
733+ anon_thp : begin. anon_thp ,
734+ file_thp : begin. file_thp ,
735+ shmem_thp : begin. shmem_thp ,
736+ inactive_anon : begin. inactive_anon ,
737+ active_anon : begin. active_anon ,
738+ inactive_file : begin. inactive_file ,
739+ active_file : begin. active_file ,
740+ unevictable : begin. unevictable ,
741+ slab_reclaimable : begin. slab_reclaimable ,
742+ slab_unreclaimable : begin. slab_unreclaimable ,
743+ ..Default :: default ( )
744+ } ;
745+ if let ( Some ( anon) , Some ( file) , Some ( kernel_stack) , Some ( pagetables) ) =
746+ ( model. anon , model. file , model. kernel_stack , model. pagetables )
747+ {
748+ model. total = Some ( anon + file + kernel_stack + pagetables) ;
749+ }
750+
751+ if let Some ( ( l, delta) ) = last {
752+ model. workingset_refault_anon = count_per_sec ! (
753+ begin. workingset_refault_anon,
754+ l. workingset_refault_anon,
755+ delta
756+ ) ;
757+ model. workingset_refault_file = count_per_sec ! (
758+ begin. workingset_refault_file,
759+ l. workingset_refault_file,
760+ delta
761+ ) ;
762+ model. workingset_activate_anon = count_per_sec ! (
763+ begin. workingset_activate_anon,
764+ l. workingset_activate_anon,
765+ delta
766+ ) ;
767+ model. workingset_activate_file = count_per_sec ! (
768+ begin. workingset_activate_file,
769+ l. workingset_activate_file,
770+ delta
771+ ) ;
772+ model. workingset_restore_anon = count_per_sec ! (
773+ begin. workingset_restore_anon,
774+ l. workingset_restore_anon,
775+ delta
776+ ) ;
777+ model. workingset_restore_file = count_per_sec ! (
778+ begin. workingset_restore_file,
779+ l. workingset_restore_file,
780+ delta
781+ ) ;
782+ model. workingset_nodereclaim = count_per_sec ! (
783+ begin. workingset_nodereclaim,
784+ l. workingset_nodereclaim,
785+ delta
786+ ) ;
787+ }
788+ model
789+ }
790+ }
656791
657792#[ cfg( test) ]
658793mod tests {
0 commit comments