Linux进程内存消耗指标解读

了解系统的内存消耗是运维最基本的技能,但是Linux中关于内存消耗的指标很容易让人混淆,本文尝试把诸多概念解释清楚

概念

物理内存和虚拟内存

物理内存:不解释;虚拟内存:进程独享,由操作系统通过地址映射的方式,转换为对物理内存的访问。在32位Linux机器上,每个进程的虚拟内存都是4G。(这里的虚拟内存与操作系统使用中过程常见的虚拟内存概念不同,不要混淆了,如Linux中swap)

内存耗用指标

  • VSS – Virtual Set Size 虚拟耗用内存(包含共享库占用的内存)
  • RSS – Resident Set Size 实际使用物理内存(包含共享库占用的内存)
  • PSS – Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存)
  • USS – Unique Set Size 进程独自占用的物理内存(不包含共享库占用的内存)

TOP命令

top - 21:58:44 up  4:45,  3 users,  load average: 2.57, 1.72, 0.75
Tasks: 108 total,   1 running, 107 sleeping,   0 stopped,   0 zombie
%Cpu(s):  5.9 us,  5.9 sy,  0.0 ni, 88.2 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  1865252 total,   542664 free,   459884 used,   862704 buff/cache
KiB Swap:  2097148 total,  2097148 free,        0 used.  1144688 avail Mem
   PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
     1 root      20   0  127936   6576   4128 S  0.0  0.4   0:01.33 systemd
     2 root      20   0       0      0      0 S  0.0  0.0   0:00.00 kthreadd
     3 root      20   0       0      0      0 S  0.0  0.0   0:00.63 ksoftirqd/0
     5 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 kworker/0:0H
  • VIRT(Virtual memory space) - 这里是虚拟内存(进程地址空间),包括数据、代码、堆、共享库、内存映射文件等,可以使用pmap命令查看详情。并不是真实内存耗费,比如我们可以通过命令java -Xms1024m -Xmx40960m Hello就可以得到VIRT为41G的进程。
  • RES(Resident set size) - 实际使用的物理内存(包含共享库占用的内存),与RSS相同
  • SHR - 与其他进程共享的内存

PS命令

$ ps aux | head
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          1  0.0  0.3 127936  6576 ?        Ss   17:12   0:01 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
root          2  0.0  0.0      0     0 ?        S    17:12   0:00 [kthreadd]

SMEM命令

smem命令可以得到USS, PSS,更能反映进程的真实内存消耗

$ smem
  PID User     Command                         Swap      USS      PSS      RSS
111965 root      -bash                              0      504      757     2164
113696 root      -bash                              0      512      779     2200
 1553 root      -bash                              0      516      783     2204
10556 root      top                                0      868      968     2292
18799 root      python /usr/bin/smem               0     4712     5169     6892
112580 root      java -Xms1024m -Xmx40960m A        0    31036    31076    32040

注意事项

  • top命令中res与ps命令rss大小一致,数据都是来自/proc/{pid}/status
  • pmap与smem中的rss大小一致,数据来自/proc/{pid}/maps
  • 但是以上两个数据却不一致,可能的原因如下: man ps得到以下解释:

The SIZE and RSS fields don't count some parts of a process including the page tables, kernel stack, struct thread_info, and struct task_struct. This is usually at least 20 KiB of memory that is always resident. SIZE is the virtual size of the process (code+data+stack).

实践

  • 不用考虑VIRT耗费情况
  • 一般也不要考虑RES内存消耗,除非一直在增大,则说明可能存在内存泄露
  • 如果系统开始出现SWAP,就需要解决RES占用过多的问题
上一篇:在 Web 浏览器上进行 RSS 阅读


下一篇:阿里云部署Tiny Tiny RSS踩坑笔记