gcore将gdb附加到进程,遍历进程的大部分虚拟内存区域并将其转储到磁盘。这是否意味着每个匿名虚拟内存都需要被分页到该进程中的内存中,从而增加其RSS,还是将内存分页到gdb进程?我猜它也会在任何文件支持的内存中分页(虽然我认为这不应该增加RSS,尽管它可能通过文件缓存增加RAM的使用)。
Kubernetes环境中的示例显示RSS从304368跳转到17135624 (gcore从工作节点调试荚运行):
# ps auxwww | head -1
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
# ps auxwww | grep 3899524 | grep -v grep
1000650+ 3899524 0.2 0.9 17229416 304368 ? SLsl Jun13 54:01 /opt/java/openjdk/jre/bin/java [...]
# gcore 3899524
[...]
# ps auxwww | grep 3899524 | grep -v grep
1000650+ 3899524 0.2 53.3 17229416 17135624 ? SLsl Jun13 54:01 /opt/java/openjdk/jre/bin/java [...]这是否具体与集装箱/cgroup有关?
发布于 2022-06-28 21:37:58
将进程的大部分内存写入文件,作为核心转储,需要读取它。确切地说,这是如何实现的,是操作系统特有的。
在大多数POSIX系统中,一个进程(或者它的分叉)被告知转储核心,无论是通过像gcore这样的调试器,还是在某些条件下死亡的任务。这样更有效,否则内存可能需要从一个地址空间复制到另一个地址空间。
在Linux上,man core记录转储的内容。/proc/[pid]/coredump_filter包含一个位掩码,允许对其进行自定义。注意,默认的集合是一些匿名或私有映射的样式。默认情况下,文件映射被排除在外,因为它们可以在任务结束后从文件中读取。
注意,在ps输出中,驻留集大小(RSS)在转储时接近虚拟内存大小(VSZ)。我假设一个16 GB的java程序,而内存的变化大部分都在堆中,可能是静态大小的,可供生产使用。一个完整的转储将触及每一页,即使它们中的大多数仍然是未触及的零。
这并不一定意味着从交换中分页。虽然这可能发生,但你提供的信息与交换无关。
核心抛出这么大的进程是很大的开销。无论是在CPU上循环遍历所有内存,还是存储来写出它。如果可能的话,避免使用开销较小的分析和调试方法。
Linux对此并没有太大的改变。主要是为您的能力规划提供更具体的说明。特定容器或systemd单元的内存使用近似于它可以创建的核心转储的大小。另见systemd-cgtop -m
https://serverfault.com/questions/1104311
复制相似问题