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

在博客文章《了解Linux上的内存使用情况》中,ps并不是一个准确的工具。

为什么ps是“错误的”根据您的看法,ps不会报告进程的实际内存使用情况。它真正要做的是显示如果只有一个进程在运行,每个进程将占用多少实际内存。当然,一台典型的Linux机器在任何给定时间都有几十个进程在运行,这意味着ps报告的VSZ和RSS数字几乎肯定是错误的。

(注:这里详细介绍了这个问题。)


当前回答

很难确定,但有两件“接近”的事情可以帮助我们。

$ ps aux

将为您提供虚拟大小(VSZ)

您还可以通过转到/proc/$pid/status从/proc文件系统获取详细的统计信息。

最重要的是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子系统。例如,对于PID为1234的进程:

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将在程序的整个生命周期内为您提供更好的内存使用情况。

Valgrind可以显示详细信息,但它会显著降低目标应用程序的速度,而且大多数时候它会改变应用程序的行为。

Exmap是我还不知道的东西,但似乎需要一个内核模块来获取信息,这可能是一个障碍。

我假设每个人都想知道关于“内存使用”的以下内容。。。在Linux中,单个进程可能使用的物理内存量大致可分为以下几类。

M.匿名映射内存-p专用.d dirty==malloc/mma映射的堆和堆栈分配和写入的内存.c clean==分配、写入、然后释放但尚未回收的malloc/mma映射的堆和堆栈内存.s已共享.d dirty==malloc/maped堆可以在写入时获得副本并在进程之间共享(已编辑).cclean==malloc/maped堆可以在写入时获得副本,并在进程之间共享(已编辑)M.n命名映射内存-p专用.d dirty==文件映射的写入内存专用.c clean==映射的程序/库文本专用映射.s已共享.d dirty==文件映射的写入内存共享.c clean==映射的库文本共享映射

Android中包含的工具showmap非常有用

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

我正在使用Arch Linux,有一个很棒的软件包叫做ps_mem:

ps_mem -p <pid>

示例输出

$ ps_mem -S -p $(pgrep firefox)

Private   +   Shared  =  RAM used   Swap used   Program

355.0 MiB +  38.7 MiB = 393.7 MiB    35.9 MiB   firefox
---------------------------------------------
                        393.7 MiB    35.9 MiB
=============================================

基于对相关问题的回答。

您可以使用SNMP获取网络上特定设备中进程的内存和CPU使用情况:)

要求:

运行进程的设备应安装并运行snmpsnmp应该配置为接受来自运行以下脚本的请求(可以在文件snmpd.conf中配置)您应该知道要监视的进程的进程ID(PID)

笔记:

HOST-ROURCES-MIB::hrSWRunPerfCPU是此进程消耗的系统CPU资源总量的秒数。请注意,在多处理器系统上,该值可能在实际(墙上时钟)时间的一厘秒内增加超过一厘秒。HOST-ROURCES-MIB::hrSWRunPerfMem是分配给此进程的实际系统内存总量。

过程监控脚本

echo "IP address: "
read ip
echo "Specfiy PID: "
read pid
echo "Interval in seconds: "
read interval

while [ 1 ]
do
    date
    snmpget -v2c -c public $ip HOST-RESOURCES-MIB::hrSWRunPerfCPU.$pid
    snmpget -v2c -c public $ip HOST-RESOURCES-MIB::hrSWRunPerfMem.$pid
    sleep $interval;
done