You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

进程ps/top RSS远低于cgroup memory.stat的原因及THP机制问询

问题背景

我们有一个运行在K8s Pod中的Go 1.19版本程序,节点上ps/top工具显示的进程RSS值远低于cgroup memory.stat中的RSS值。

cgroup memory.stat 内容

$ cat memory.stat

cache 547885056
rss 7860129792    <--  cgroup中的rss远高于"ps -aux"的值
rss_huge 5066719232  <-- 注意这里rss_huge数值也很高
shmem 0
mapped_file 0
dirty 20480
writeback 0
swap 0
pgpgin 450943252
pgpgout 450125090
pgfault 1097413913
pgmajfault 0
inactive_anon 0
active_anon 7859318784
inactive_file 546922496
active_file 962560
unevictable 0
hierarchical_memory_limit 12884901888
hierarchical_memsw_limit 12884901888
total_cache 547885056
total_rss 7860129792
total_rss_huge 5066719232
total_shmem 0
total_mapped_file 0
total_dirty 20480
total_writeback 0
total_swap 0
total_pgpgin 450943252
total_pgpgout 450125090
total_pgfault 1097413913
total_pgmajfault 0
total_inactive_anon 0
total_active_anon 7859318784
total_inactive_file 546922496
total_active_file 962560
total_unevictable 0

docker stats 输出

$ docker stats c39bc01d525e

CONTAINER ID          CPU %               MEM USAGE / LIMIT   MEM %               NET I/O             BLOCK I/O           PIDS
c39bc01d525e          49.27%              7.88GiB / 12GiB            65.67%              0B / 0B             0B / 24.6kB         106

进程RSS统计

该cgroup管理3个进程,主进程PID为496687,其RSS仅为5205340,远低于cgroup和docker stats的数值:

$ cat cgroup.procs 
496644
496687
496688

$ ps -aux | grep -E "496644|496687|496688"

USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root     496644  0.0  0.0   1604  1464 ?        Ss   Oct28   0:00 sh ./bin/start.sh
root     496687 26.5  0.4 6466348 5205340 ?     Sl   Oct28 7271:55 /go/release/bin/golang-app
root     496688  0.0  0.0   1588   608 ?        S    Oct28   0:31 tail -f /dev/null

smaps 统计细节

通过smaps统计主进程的内存指标,总和与ps显示接近,但仍远低于cgroup数值:

# Rss总和
$ cat /proc/496687/smaps | grep Rss | awk -F':' '{print $2 }' | awk 'BEGIN {sum=0} {sum+=$1} END {print sum}'
4645704

# AnonHugePages总和
$ cat /proc/496687/smaps | grep AnonHugePages | awk -F':' '{print $2 }' | awk 'BEGIN {sum=0} {sum+=$1} END {print sum}'
524288

# Size总和
$ cat /proc/496687/smaps | grep -E "^Size:" | awk -F':' '{print $2 }' | awk 'BEGIN {sum=0} {sum+=$1} END {print sum}'
6466352

THP配置

$ cat /sys/kernel/mm/transparent_hugepage/enabled 
[always] madvise never

$ cat /sys/kernel/mm/transparent_hugepage/defrag 
always defer defer+madvise [madvise] never

$ cat /sys/kernel/mm/transparent_hugepage/shmem_enabled 
always within_size advise [never] deny force

系统信息

已关闭swap,无swap缓存:

$ uname -a
Linux 4.14.15-1.el7.elrepo.x86_64 #1 SMP Tue Jan 23 20:28:26 EST 2018 x86_64 x86_64 x86_64 GNU/Linux

$ cat /etc/redhat-release 
Red Hat Enterprise Linux Server release 7.9 (Maipo)

问题与解答

1. 导致ps/top显示的RSS远低于cgroup memory.stat中RSS的原因是什么?

核心原因是透明大页(THP)的统计方式差异:

  • cgroup的rss统计的是实际分配给该cgroup的物理内存总量,包含所有已分配的内存页,包括THP的完整大小(默认2MB/页),即使THP中只有部分内存被进程实际使用。
  • 而ps/top的RSS统计的是进程实际映射并主动使用的内存页,对于THP,只会统计其中被进程实际写入/访问的部分,未被使用的THP空间不会被计入进程RSS,但会被cgroup统计为已分配的内存。

结合你的数据,cgroup中rss_huge高达5GB左右,这部分就是未被进程完全使用但已被分配的THP空间,是两者数值差异的主要来源。

2. 根据kernel文档,cgroup memory.stat中的rss包含transparent hugepages,THP是否也会被计入ps/top显示的RSS?

THP会被计入ps/top的RSS,但统计逻辑不同:

  • cgroup的rss直接按THP的完整页大小统计,只要THP被分配给cgroup下的进程,不管是否被完全使用,都会全额计入。
  • ps/top的RSS只统计THP中被进程实际访问、写入的部分,未被使用的THP内存不会被统计到进程的RSS中。

这就导致同样的THP资源,在cgroup和ps/top中的统计值出现巨大差距。

3. 若差异由THP导致,其影响内存统计的机制是什么?

THP影响内存统计的核心机制在于内存页的分配与使用统计逻辑差异:

  1. THP分配逻辑:当THP开启(你的配置是always),内核会优先为进程分配2MB的大页,而非常规4KB小页。即使进程只需要少量内存,内核也可能提前分配完整的THP。
  2. cgroup统计逻辑:cgroup的内存统计以“已分配给该cgroup的物理内存”为基准,只要THP被分配给cgroup下的进程,不管是否被使用,都会按完整2MB大小计入rss和rss_huge。
  3. ps/top统计逻辑:ps/top读取的是/proc/[pid]/stat中的RSS值,该值统计的是进程实际“驻留”在物理内存中且被主动使用的页面,对于THP,只有其中被进程实际访问过的部分会被计数,未被使用的空间不会被统计。

简单来说,cgroup统计的是“已分配给容器的内存”,而ps/top统计的是“进程实际在使用的内存”,THP的预分配特性放大了两者的统计差异。


内容的提问来源于stack exchange,提问作者jim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 01:10:57