smem是唯一能直接获取USS和PSS的标准工具,它通过解析/proc/[pid]/smaps按页统计共享关系,准确计算出各进程独占内存(USS)及按比例分摊的共享内存(PSS),而top、ps等工具仅提供RSS且无法反映真实物理内存占用。

smem 命令是唯一能直接查 USS 和 PSS 的标准工具
Linux 内核本身不导出 USS/PSS 这类聚合指标,/proc/[pid]/smaps 只提供 Private_Dirty、Shared_Clean 等原始分项,需要自己加总计算。而 smem 就是专为解决这个问题写的——它遍历所有 /proc/[pid]/smaps,按页粒度统计共享关系,再分别算出每个进程的 USS(全部 private 页)、PSS(private + shared/参与进程数)。没有 smem,你得写脚本解析 smaps 才能得到近似值,误差还大。
查全系统进程 USS/PSS:用 smem -s uss -r -p 或 smem -s pss -r -p
默认输出列太多,干扰判断。实际排查时只关心三列:PID、USS(或 PSS)、Command。加参数控制排序和格式:
-
-s uss:按 USS 升序(小→大),加-r变成降序(大→小) -
-p:所有内存数值显示为占系统总物理内存的百分比(如USS%列是 0.87%,代表独占整机 RAM 的 0.87%) - 管道接
| head -15快速看前 15 个“最吃独占内存”的进程
示例命令:smem -s uss -r -p | head -15。注意:USS 恒 ≤ PSS ≤ RSS,如果某进程 USS 接近 RSS,说明它几乎没共享库(比如静态链接的 C 工具);如果 USS 只有 RSS 的 1/5,那它高度依赖共享(如 Chrome、Java 应用)。
只查特定进程(如 java、nginx)的 USS/PSS:用 -P 正则匹配
线上服务常有多个同名进程(比如十几个 java),但你想知道“哪个 Java 实例 USS 最高”,不能靠 ps aux | grep java —— 那只给 RSS,且无法区分共享影响。
-
smem -P 'java' -s uss -r -p:匹配命令行含java的所有进程(大小写敏感) - 加
-i忽略大小写:smem -i -P 'JAVA' - 想精确匹配启动命令,可用完整路径正则,例如:
smem -P '^/usr/bin/java'
常见误操作:用 ps aux | grep java 后再人工加总 RSS,结果发现总和远超物理内存——那是把共享代码页重复算了十几遍。USS 才是真实增量成本,杀掉它才真正释放内存。
为什么不用 top/ps 查 USS?它们根本不提供这个字段
top 的 RES 列就是 RSS,ps 的 RSS 列也是 RSS,两者都包含共享部分。它们连 PSS 都不支持,更别说 USS。试图用 ps aux --sort=-rss 找“最耗内存进程”,本质是在找“最常加载共享库的进程”,不是“最占物理内存的进程”。
- USS 是唯一能回答“杀掉这个进程,我能拿回多少真实物理内存”的指标
- 当
MemAvailable低于 500MB 且smem -s uss -r | head -5显示几个进程 USS 总和已超 2GB,基本可断定是这些进程导致内存紧张 - USS 不会出现在
/proc/[pid]/status或/proc/[pid]/statm中,必须依赖smem或手动解析smaps
真正容易被忽略的是:USS 数值在进程生命周期中波动剧烈。刚启动的 Java 进程 USS 可能只有 20MB,加载完 Spring Boot Starter 后涨到 300MB,GC 后又回落——所以排查泄漏必须连续采样,单次快照意义有限。


















