linux - 如何衡量一个应用程序或者进程实际内存使用量的?

  显示原文与译文双语对照的内容

如何度量Linux中应用程序或者进程的内存使用情况?

的博客文章了解 Linux的内存使用情况,"ps"不是用于这个目的的准确工具。

为什么 ps 是"错误"

根据你看待它的方式,。 没有报告进程的实际内存使用情况。 它真的在做什么显示每个进程会占用,如果它是运行的唯一进程多少实际内存。 当然,一个典型的Linux机器在任何给定时间都有几十个进程运行,这意味着"错误"报告的VSZ和RSS数字几乎是。

时间:

使用 ps 或者类似的工具,你将只获取由该进程分配的内存页数。 这个号码是正确的,但是:

  • 不反映应用程序使用的实际内存量,只反映为它保留的内存量

  • 如果页面是共享的,可能会引起误解,例如由几个线程或者使用动态链接的库

如果你真的想知道你的应用程序实际使用了多少内存,你需要在一个分析器中运行它。 例如 valgrind 可以让你了解所使用的内存量,更重要的是,在你的程序中可能有内存泄漏。

很难确定,但这里有两个"关闭"可以帮助你。


$ ps aux 

将给你虚拟的大小( VSZ )

你还可以从/proc 文件系统 获取详细的统计数据,转到 /proc/$pid/status

最重要的是 VmSize,它应该接近 ps aux 所提供的。

/proc/19420$ cat status
Name: firefox
State: S (sleeping)
Tgid: 19420
Pid: 19420
PPid: 1
TracerPid: 0
Uid: 1000 1000 1000 1000
Gid: 1000 1000 1000 1000
FDSize: 256
Groups: 4 6 20 24 25 29 30 44 46 107 109 115 124 1000 
VmPeak: 222956 kB
VmSize: 212520 kB
VmLck: 0 kB
VmHWM: 127912 kB
VmRSS: 118768 kB
VmData: 170180 kB
VmStk: 228 kB
VmExe: 28 kB
VmLib: 35424 kB
VmPTE: 184 kB
Threads: 8
SigQ: 0/16382
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000020001000
SigCgt: 000000018000442f
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
Cpus_allowed: 03
Mems_allowed: 1
voluntary_ctxt_switches: 63422
nonvoluntary_ctxt_switches: 7171

在最新版本的linux中,使用 - smaps 子系统。 例如对于具有 1234个PID的进程:

 
cat/proc/1234/smaps

 

它将告诉你在那个时候它使用了多少内存。 更重要的是,它将把内存分成私有和共享,从而可以知道你的程序的实例正在使用多少内存,在不含内存该程序的多个实例之间共享。

没有简单的方法来计算这个。 但有些人试图获得一些好的答案:

这里没有一个答案,因为你不能精确地指出一个进程所占用的内存量。 linux下的大多数进程使用共享库。 例如假设你想计算'ls'进程的内存使用。 你只计算可以执行'ls'使用的内存( 如果可以将它的隔离)? 如何运行 libc或者运行'ls'所需的所有其他库?


linux-gate.so.1 => (0x00ccb000)
librt.so.1 =>/lib/librt.so.1 (0x06bc7000)
libacl.so.1 =>/lib/libacl.so.1 (0x00230000)
libselinux.so.1 =>/lib/libselinux.so.1 (0x00162000)
libc.so.6 =>/lib/libc.so.6 (0x00b40000)
libpthread.so.0 =>/lib/libpthread.so.0 (0x00cb4000)
/lib/ld-linux.so.2 (0x00b1d000)
libattr.so.1 =>/lib/libattr.so.1 (0x00229000)
libdl.so.2 =>/lib/libdl.so.2 (0x00cae000)
libsepol.so.1 =>/lib/libsepol.so.1 (0x0011a000)

你可以认为它们是由其他进程共享的,但是'ls'不能在没有加载它们的系统上运行。

另外,如果你需要知道一个进程需要多少内存才能进行容量规划,你必须计算每个额外的过程的额外副本。 我想/proc/PID/status 可能会在一次给你足够的内存使用信息。 另一方面,valgrind将在程序的整个生命周期内提供更好的内存使用配置文件

如果你的代码是在C 或者你可能能够使用 getrusage() C++ 它返回你在流程中的各种统计信息关于内存和时间的使用

于该memory-use相关options,并非所有平台都支持这个虽然,因此将返回 0 values.

相反,你可以查看 /proc/[pid]/statm 中创建的虚拟文件( 其中 [pid] 被你的进程标识替换) 。 你可以从 getprocessid() 获得这里信息。

这个文件看起来像一个带有 7个整数的文本文件。 你可能对这个文件中的第一个( 所有内存使用) 和第六个( 数据内存使用) 数字最感兴趣。

Valgrind 可以显示详细的信息,但它 目标应用程序明显缓慢下来,而且在大多数时间里它改变这个应用程序的行为。
Exmap 中是一些我还不知道,不过好像你需要一个内核模块来得到信息,这可能是一个障碍。

我假设每个人都想知道的"内存使用情况"是以下内容。。
在linux中,单个进程可能使用的物理内存可以大致分为以下几类。

  • M.a 匿名映射内存

    • 私人
      • 已经分配的== malloc/mmapped堆和堆栈和写入内存
      • 清除 == malloc/mmapped堆和堆栈内存一旦分配,写入,释放,但还没有回收
    • 共享
      • d 脏 == malloc/mmaped堆能得到 copy-on-write和之间共享进程( 编辑)
      • c 干净 == malloc/mmaped堆能得到 copy-on-write和之间共享进程( 编辑)
  • M.n 命名映射内存

    • 私人
      • d 脏==文件mmapped写入内存私有
      • 清除==映射的程序/库文本私有映射
    • 共享
      • ==脏文件mmapped写入共享内存
      • c 清除==映射的库文本共享映射

安卓系统称为 showmap 相当useful,实用程序包括


virtual shared shared private private
size RSS PSS clean dirty clean dirty object
-------- -------- -------- -------- -------- -------- -------- ------------------------------
 4 0 0 0 0 0 0 0:00 0 [vsyscall]
 4 4 0 4 0 0 0 [vdso]
 88 28 28 0 0 4 24 [stack]
 12 12 12 0 0 0 12 7909/lib/ld-2.11.1.so
 12 4 4 0 0 0 4 89529/usr/lib/locale/en_US.utf8/LC_IDENTIFICATION
 28 0 0 0 0 0 0 86661/usr/lib/gconv/gconv-modules.cache
 4 0 0 0 0 0 0 87660/usr/lib/locale/en_US.utf8/LC_MEASUREMENT
 4 0 0 0 0 0 0 89528/usr/lib/locale/en_US.utf8/LC_TELEPHONE
 4 0 0 0 0 0 0 89527/usr/lib/locale/en_US.utf8/LC_ADDRESS
 4 0 0 0 0 0 0 87717/usr/lib/locale/en_US.utf8/LC_NAME
 4 0 0 0 0 0 0 87873/usr/lib/locale/en_US.utf8/LC_PAPER
 4 0 0 0 0 0 0 13879/usr/lib/locale/en_US.utf8/LC_MESSAGES/SYS_LC_MESSAGES
 4 0 0 0 0 0 0 89526/usr/lib/locale/en_US.utf8/LC_MONETARY
 4 0 0 0 0 0 0 89525/usr/lib/locale/en_US.utf8/LC_TIME
 4 0 0 0 0 0 0 11378/usr/lib/locale/en_US.utf8/LC_NUMERIC
 1156 8 8 0 0 4 4 11372/usr/lib/locale/en_US.utf8/LC_COLLATE
 252 0 0 0 0 0 0 11321/usr/lib/locale/en_US.utf8/LC_CTYPE
 128 52 1 52 0 0 0 7909/lib/ld-2.11.1.so
 2316 32 11 24 0 0 8 7986/lib/libncurses.so.5.7
 2064 8 4 4 0 0 4 7947/lib/libdl-2.11.1.so
 3596 472 46 440 0 4 28 7933/lib/libc-2.11.1.so
 2084 4 0 4 0 0 0 7995/lib/libnss_compat-2.11.1.so
 2152 4 0 4 0 0 0 7993/lib/libnsl-2.11.1.so
 2092 0 0 0 0 0 0 8009/lib/libnss_nis-2.11.1.so
 2100 0 0 0 0 0 0 7999/lib/libnss_files-2.11.1.so
 3752 2736 2736 0 0 864 1872 [heap]
 24 24 24 0 0 0 24 [anon]
 916 616 131 584 0 0 32/bin/bash
-------- -------- -------- -------- -------- -------- -------- ------------------------------
 22816 4004 3005 1116 0 876 2012 TOTAL

...