Cgroup 和程序記憶體統計資訊不匹配
我正在嘗試設置一些監視以查看服務何時使用過多記憶體。可以從兩個地方讀取記憶體使用情況:
- 用於
/proc/<pid>/status
pid,或- 用於執行它的
/sys/fs/cgroup/<group-id>/memory.stat
對照組。該服務由 systemd 啟動,因此它擁有自己的控制組,並且因為它有時會啟動我需要包含在統計資訊中的子程序,並且由於路徑在重新啟動時是恆定的,所以控制組統計資訊更合適。
不幸的是,數字似乎不匹配。以下是沒有子程序執行時的值範例(命令與執行完全相同,除了服務名稱,結果與獲取完全相同,除了與記憶體相關的項目被刪除):
# cat /sys/fs/cgroup/system.slice/some.service/memory.stat /proc/$(cat /sys/fs/cgroup/system.slice/some.service/cgroup.procs)/status anon 5873664 file 2408448 kernel_stack 491520 slab 962560 sock 0 shmem 61440 file_mapped 405504 file_dirty 0 file_writeback 0 inactive_anon 0 active_anon 5853184 inactive_file 1916928 active_file 360448 unevictable 0 slab_reclaimable 270336 slab_unreclaimable 692224 pgfault 60258 pgmajfault 99 pgrefill 0 pgscan 0 pgsteal 0 pgactivate 0 pgdeactivate 0 pglazyfree 0 pglazyfreed 0 workingset_refault 0 workingset_activate 0 workingset_nodereclaim 0 … VmPeak: 494812 kB VmSize: 494164 kB VmLck: 0 kB VmPin: 0 kB VmHWM: 25836 kB VmRSS: 25484 kB RssAnon: 5468 kB RssFile: 20016 kB RssShmem: 0 kB VmData: 464776 kB VmStk: 132 kB VmExe: 180 kB VmLib: 23940 kB VmPTE: 156 kB VmSwap: 0 kB voluntary_ctxt_switches: 9 nonvoluntary_ctxt_switches: 620
我會認為過程統計中的適當值是
VmRSS
(=RssAnon
+RssFile
+RssShmem
)。但是,雖然我認為anon
小組應該RssAnon
屬於過程,file
小組應該RssFile
屬於過程,但它們並不匹配。雖然anon
是 5736 KB,RssAnon
但只有 5468 KB,而對於文件來說差異更大,file
只有 2352 KB,但RssFile
為 20016 KB,幾乎是數量級的差異。還有
memory.current
一個值與anon
+file
+kernel_stack
+slab
+sock
+大致匹配的文件shmem
,但我在程序狀態中看不到任何匹配值。那麼為什麼這些數字如此不同,哪些數字更能說明應用程序對系統施加的記憶體壓力呢?
注意:在核心 4.19.72(稍微陳舊的嵌入式 BSP)上使用 cgroup2。
來自控制組 v2指南:
**一個記憶體區域被實例化它的 cgroup 負責,**並一直由 cgroup 負責,直到該區域被釋放。將程序遷移到不同的 cgroup 不會將它在前一個 cgroup 中實例化的記憶體使用量移動到新的 cgroup。
屬於不同 cgroup 的程序可以使用記憶體區域。該區域將向哪個 cgroup 收費是不確定的;然而,隨著時間的推移,記憶體區域很可能最終會出現在一個有足夠記憶體餘量以避免高回收壓力的 cgroup 中。
file
因此,我們將從in cgroups 和RssFile
in之間的區別開始/proc/<pid>/status
:該程序可能已經打開了 20016 KB 的文件,但這些文件頁面可能之前已經存在於記憶體記憶體中,因為其他程序已經打開了它們,並且它們各自的 cgroup 對它們收費。因此,在這 20016 KB 中,只有 2352 KB 由 cgroup 收費,其餘的屬於其他 cgroup(以及之前載入這些文件的程序)。
anon
關於in cgroups 和RssAnon
in之間的區別/proc/<pid>/status
,我沒有任何好的解釋。關於
memory.current
,據我所知,所有核心內部結構(如kernel_stack
和slab
)僅在 cgroup 中可見,並且您看不到這些數字的每個程序的統計資訊,因為/proc/<pid>/status
僅顯示使用者空間記憶體資訊。