smem比top/ps更精准,因其基于/proc解析smaps精确计算USS(独占内存)和PSS(共享页均摊),避免RSS重复统计共享库导致的高估。

要精确分析物理内存占用,必须绕开 top 和 ps 显示的 RSS——它把共享库重复算进每个进程,总和常超物理内存总量;真正可信的是 USS(Unique Set Size),而 smem 是少数能稳定提取并排序 USS 的工具。
为什么 smem 的 USS 比 RSS 更可靠
RSS 把所有驻留物理页都计入,包括 libc.so、libstdc++.so 等被几十个进程共用的页;USS 则只统计该进程独占、未被任何其他进程映射的物理页。比如一个 Java 进程 RSS 是 1.2 GB,但 USS 可能只有 180 MB——那多出来的 1 GB 很可能全是共享类库和 JVM 元空间。
-
USS ≤ PSS ≤ RSS,三者差距越大,说明该进程越依赖共享内存 - 容器环境里,若某 Pod 的
USS持续上涨而RSS平稳,大概率是应用层缓存泄漏,不是共享库问题 -
/proc/<pid>/statm</pid>不含 USS 字段,smem必须解析/proc/<pid>/smaps</pid>中的MMUPageSize和MMUPFPageSize才能推导出 USS,内核需开启CONFIG_PROC_PAGE_MONITOR(主流发行版默认启用)
按 USS 排序查内存大户的实操命令
直接运行 smem 默认不排序、带表头、单位是 KB 且无百分比,不适合快速定位。常用组合如下:
-
smem -s uss -r --no-header | head -20:按 USS 降序取前 20,适合终端快速扫视 -
smem -s uss -r -p | head -15:加-p后所有数值转为占系统总内存的百分比,USS%列一眼看出“这个进程吃掉了整机多少 RAM” -
smem -P 'nginx' -s uss -r -p:用正则匹配进程名,只看 nginx 相关 worker,避免被systemd或bash干扰 -
smem -U www-data -s uss -r:按用户聚合,查www-data下所有进程的 USS 总和,适合 Web 服务排查
常见误判与避坑点
很多人用 smem 后仍判断错误,问题往往出在数据解读或权限上:
- 没加
sudo:普通用户只能看到自己启动的进程,root进程(如mysqld、dockerd)的 USS 完全不可见 - 混淆
-p和--pcnt:-p是全局百分比,--pcnt是列内相对占比(已弃用,新版不推荐) - 在 cgroup v2 容器中漏挂
/proc:Docker 默认以rprivate挂载/proc,导致smem读不到smaps,报错类似Permission denied或 USS 全为 0 - 忽略时间维度:单次快照无法判断泄漏,应配合
watch -n 5 'smem -s uss -r | head -10'观察 USS 是否持续增长
USS 不是万能指标——它无法反映堆外内存(如 Netty Direct Buffer)、mmap 映射文件或 tmpfs 占用;但对绝大多数常规进程(Java、Python、Node.js、Nginx),USS 就是内存是否失控的第一道标尺。别跳过 -s uss -r 这两个参数,它们才是让 smem 从“能用”变成“真准”的关键。


















