我正在尝试设置一些监控来查看服务何时使用过多内存。可以从两个地方读取内存使用情况:
- 为
/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 上使用 cgroup2(稍微过时的嵌入式 BSP)。
答案1
来自对照组 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
仅显示用户空间内存信息。