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

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

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

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


当前回答

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
=============================================

如果您想要比使用Valgrind进行评测更快的东西,并且您的内核更旧,而且您不能使用smaps,那么一个带有显示进程驻留集选项的ps(使用ps-o rss,命令)可以让您快速、合理地了解所使用的非交换内存的实际数量。

ps -eo size,pid,user,command --sort -size | \
    awk '{ hr=$1/1024 ; printf("%13.2f Mb ",hr) } { for ( x=4 ; x<=NF ; x++ ) { printf("%s ",$x) } print "" }' |\
    cut -d "" -f2 | cut -d "-" -f1

使用此作为根,您可以获得每个进程的内存使用情况的清晰输出。

输出示例:

     0.00 Mb COMMAND
  1288.57 Mb /usr/lib/firefox
   821.68 Mb /usr/lib/chromium/chromium
   762.82 Mb /usr/lib/chromium/chromium
   588.36 Mb /usr/sbin/mysqld
   547.55 Mb /usr/lib/chromium/chromium
   523.92 Mb /usr/lib/tracker/tracker
   476.59 Mb /usr/lib/chromium/chromium
   446.41 Mb /usr/bin/gnome
   421.62 Mb /usr/sbin/libvirtd
   405.11 Mb /usr/lib/chromium/chromium
   302.60 Mb /usr/lib/chromium/chromium
   291.46 Mb /usr/lib/chromium/chromium
   284.56 Mb /usr/lib/chromium/chromium
   238.93 Mb /usr/lib/tracker/tracker
   223.21 Mb /usr/lib/chromium/chromium
   197.99 Mb /usr/lib/chromium/chromium
   194.07 Mb conky
   191.92 Mb /usr/lib/chromium/chromium
   190.72 Mb /usr/bin/mongod
   169.06 Mb /usr/lib/chromium/chromium
   155.11 Mb /usr/bin/gnome
   136.02 Mb /usr/lib/chromium/chromium
   125.98 Mb /usr/lib/chromium/chromium
   103.98 Mb /usr/lib/chromium/chromium
    93.22 Mb /usr/lib/tracker/tracker
    89.21 Mb /usr/lib/gnome
    80.61 Mb /usr/bin/gnome
    77.73 Mb /usr/lib/evolution/evolution
    76.09 Mb /usr/lib/evolution/evolution
    72.21 Mb /usr/lib/gnome
    69.40 Mb /usr/lib/evolution/evolution
    68.84 Mb nautilus
    68.08 Mb zeitgeist
    60.97 Mb /usr/lib/tracker/tracker
    59.65 Mb /usr/lib/evolution/evolution
    57.68 Mb apt
    55.23 Mb /usr/lib/gnome
    53.61 Mb /usr/lib/evolution/evolution
    53.07 Mb /usr/lib/gnome
    52.83 Mb /usr/lib/gnome
    51.02 Mb /usr/lib/udisks2/udisksd
    50.77 Mb /usr/lib/evolution/evolution
    50.53 Mb /usr/lib/gnome
    50.45 Mb /usr/lib/gvfs/gvfs
    50.36 Mb /usr/lib/packagekit/packagekitd
    50.14 Mb /usr/lib/gvfs/gvfs
    48.95 Mb /usr/bin/Xwayland :1024
    46.21 Mb /usr/bin/gnome
    42.43 Mb /usr/bin/zeitgeist
    42.29 Mb /usr/lib/gnome
    41.97 Mb /usr/lib/gnome
    41.64 Mb /usr/lib/gvfs/gvfsd
    41.63 Mb /usr/lib/gvfs/gvfsd
    41.55 Mb /usr/lib/gvfs/gvfsd
    41.48 Mb /usr/lib/gvfs/gvfsd
    39.87 Mb /usr/bin/python /usr/bin/chrome
    37.45 Mb /usr/lib/xorg/Xorg vt2
    36.62 Mb /usr/sbin/NetworkManager
    35.63 Mb /usr/lib/caribou/caribou
    34.79 Mb /usr/lib/tracker/tracker
    33.88 Mb /usr/sbin/ModemManager
    33.77 Mb /usr/lib/gnome
    33.61 Mb /usr/lib/upower/upowerd
    33.53 Mb /usr/sbin/gdm3
    33.37 Mb /usr/lib/gvfs/gvfsd
    33.36 Mb /usr/lib/gvfs/gvfs
    33.23 Mb /usr/lib/gvfs/gvfs
    33.15 Mb /usr/lib/at
    33.15 Mb /usr/lib/at
    30.03 Mb /usr/lib/colord/colord
    29.62 Mb /usr/lib/apt/methods/https
    28.06 Mb /usr/lib/zeitgeist/zeitgeist
    27.29 Mb /usr/lib/policykit
    25.55 Mb /usr/lib/gvfs/gvfs
    25.55 Mb /usr/lib/gvfs/gvfs
    25.23 Mb /usr/lib/accountsservice/accounts
    25.18 Mb /usr/lib/gvfs/gvfsd
    25.15 Mb /usr/lib/gvfs/gvfs
    25.15 Mb /usr/lib/gvfs/gvfs
    25.12 Mb /usr/lib/gvfs/gvfs
    25.10 Mb /usr/lib/gnome
    25.10 Mb /usr/lib/gnome
    25.07 Mb /usr/lib/gvfs/gvfsd
    24.99 Mb /usr/lib/gvfs/gvfs
    23.26 Mb /usr/lib/chromium/chromium
    22.09 Mb /usr/bin/pulseaudio
    19.01 Mb /usr/bin/pulseaudio
    18.62 Mb (sd
    18.46 Mb (sd
    18.30 Mb /sbin/init
    18.17 Mb /usr/sbin/rsyslogd
    17.50 Mb gdm
    17.42 Mb gdm
    17.09 Mb /usr/lib/dconf/dconf
    17.09 Mb /usr/lib/at
    17.06 Mb /usr/lib/gvfs/gvfsd
    16.98 Mb /usr/lib/at
    16.91 Mb /usr/lib/gdm3/gdm
    16.86 Mb /usr/lib/gvfs/gvfsd
    16.86 Mb /usr/lib/gdm3/gdm
    16.85 Mb /usr/lib/dconf/dconf
    16.85 Mb /usr/lib/dconf/dconf
    16.73 Mb /usr/lib/rtkit/rtkit
    16.69 Mb /lib/systemd/systemd
    13.13 Mb /usr/lib/chromium/chromium
    13.13 Mb /usr/lib/chromium/chromium
    10.92 Mb anydesk
     8.54 Mb /sbin/lvmetad
     7.43 Mb /usr/sbin/apache2
     6.82 Mb /usr/sbin/apache2
     6.77 Mb /usr/sbin/apache2
     6.73 Mb /usr/sbin/apache2
     6.66 Mb /usr/sbin/apache2
     6.64 Mb /usr/sbin/apache2
     6.63 Mb /usr/sbin/apache2
     6.62 Mb /usr/sbin/apache2
     6.51 Mb /usr/sbin/apache2
     6.25 Mb /usr/sbin/apache2
     6.22 Mb /usr/sbin/apache2
     3.92 Mb bash
     3.14 Mb bash
     2.97 Mb bash
     2.95 Mb bash
     2.93 Mb bash
     2.91 Mb bash
     2.86 Mb bash
     2.86 Mb bash
     2.86 Mb bash
     2.84 Mb bash
     2.84 Mb bash
     2.45 Mb /lib/systemd/systemd
     2.30 Mb (sd
     2.28 Mb /usr/bin/dbus
     1.84 Mb /usr/bin/dbus
     1.46 Mb ps
     1.21 Mb openvpn hackthebox.ovpn
     1.16 Mb /sbin/dhclient
     1.16 Mb /sbin/dhclient
     1.09 Mb /lib/systemd/systemd
     0.98 Mb /sbin/mount.ntfs /dev/sda3 /media/n0bit4/Data
     0.97 Mb /lib/systemd/systemd
     0.96 Mb /lib/systemd/systemd
     0.89 Mb /usr/sbin/smartd
     0.77 Mb /usr/bin/dbus
     0.76 Mb su
     0.76 Mb su
     0.76 Mb su
     0.76 Mb su
     0.76 Mb su
     0.76 Mb su
     0.75 Mb sudo su
     0.75 Mb sudo su
     0.75 Mb sudo su
     0.75 Mb sudo su
     0.75 Mb sudo su
     0.75 Mb sudo su
     0.74 Mb /usr/bin/dbus
     0.71 Mb /usr/lib/apt/methods/http
     0.68 Mb /bin/bash /usr/bin/mysqld_safe
     0.68 Mb /sbin/wpa_supplicant
     0.66 Mb /usr/bin/dbus
     0.61 Mb /lib/systemd/systemd
     0.54 Mb /usr/bin/dbus
     0.46 Mb /usr/sbin/cron
     0.45 Mb /usr/sbin/irqbalance
     0.43 Mb logger
     0.41 Mb awk { hr=$1/1024 ; printf("%13.2f Mb ",hr) } { for ( x=4 ; x<=NF ; x++ ) { printf("%s ",$x) } print "" }
     0.40 Mb /usr/bin/ssh
     0.34 Mb /usr/lib/chromium/chrome
     0.32 Mb cut
     0.32 Mb cut
     0.00 Mb [kthreadd]
     0.00 Mb [ksoftirqd/0]
     0.00 Mb [kworker/0:0H]
     0.00 Mb [rcu_sched]
     0.00 Mb [rcu_bh]
     0.00 Mb [migration/0]
     0.00 Mb [lru
     0.00 Mb [watchdog/0]
     0.00 Mb [cpuhp/0]
     0.00 Mb [cpuhp/1]
     0.00 Mb [watchdog/1]
     0.00 Mb [migration/1]
     0.00 Mb [ksoftirqd/1]
     0.00 Mb [kworker/1:0H]
     0.00 Mb [cpuhp/2]
     0.00 Mb [watchdog/2]
     0.00 Mb [migration/2]
     0.00 Mb [ksoftirqd/2]
     0.00 Mb [kworker/2:0H]
     0.00 Mb [cpuhp/3]
     0.00 Mb [watchdog/3]
     0.00 Mb [migration/3]
     0.00 Mb [ksoftirqd/3]
     0.00 Mb [kworker/3:0H]
     0.00 Mb [kdevtmpfs]
     0.00 Mb [netns]
     0.00 Mb [khungtaskd]
     0.00 Mb [oom_reaper]
     0.00 Mb [writeback]
     0.00 Mb [kcompactd0]
     0.00 Mb [ksmd]
     0.00 Mb [khugepaged]
     0.00 Mb [crypto]
     0.00 Mb [kintegrityd]
     0.00 Mb [bioset]
     0.00 Mb [kblockd]
     0.00 Mb [devfreq_wq]
     0.00 Mb [watchdogd]
     0.00 Mb [kswapd0]
     0.00 Mb [vmstat]
     0.00 Mb [kthrotld]
     0.00 Mb [ipv6_addrconf]
     0.00 Mb [acpi_thermal_pm]
     0.00 Mb [ata_sff]
     0.00 Mb [scsi_eh_0]
     0.00 Mb [scsi_tmf_0]
     0.00 Mb [scsi_eh_1]
     0.00 Mb [scsi_tmf_1]
     0.00 Mb [scsi_eh_2]
     0.00 Mb [scsi_tmf_2]
     0.00 Mb [scsi_eh_3]
     0.00 Mb [scsi_tmf_3]
     0.00 Mb [scsi_eh_4]
     0.00 Mb [scsi_tmf_4]
     0.00 Mb [scsi_eh_5]
     0.00 Mb [scsi_tmf_5]
     0.00 Mb [bioset]
     0.00 Mb [kworker/1:1H]
     0.00 Mb [kworker/3:1H]
     0.00 Mb [kworker/0:1H]
     0.00 Mb [kdmflush]
     0.00 Mb [bioset]
     0.00 Mb [kdmflush]
     0.00 Mb [bioset]
     0.00 Mb [jbd2/sda5
     0.00 Mb [ext4
     0.00 Mb [kworker/2:1H]
     0.00 Mb [kauditd]
     0.00 Mb [bioset]
     0.00 Mb [drbd
     0.00 Mb [irq/27
     0.00 Mb [i915/signal:0]
     0.00 Mb [i915/signal:1]
     0.00 Mb [i915/signal:2]
     0.00 Mb [ttm_swap]
     0.00 Mb [cfg80211]
     0.00 Mb [kworker/u17:0]
     0.00 Mb [hci0]
     0.00 Mb [hci0]
     0.00 Mb [kworker/u17:1]
     0.00 Mb [iprt
     0.00 Mb [iprt
     0.00 Mb [kworker/1:0]
     0.00 Mb [kworker/3:0]
     0.00 Mb [kworker/0:0]
     0.00 Mb [kworker/2:0]
     0.00 Mb [kworker/u16:0]
     0.00 Mb [kworker/u16:2]
     0.00 Mb [kworker/3:2]
     0.00 Mb [kworker/2:1]
     0.00 Mb [kworker/1:2]
     0.00 Mb [kworker/0:2]
     0.00 Mb [kworker/2:2]
     0.00 Mb [kworker/0:1]
     0.00 Mb [scsi_eh_6]
     0.00 Mb [scsi_tmf_6]
     0.00 Mb [usb
     0.00 Mb [bioset]
     0.00 Mb [kworker/3:1]
     0.00 Mb [kworker/u16:1]

/prox/xxx/numa_maps提供了一些信息:N0=???N1=???。但这个结果可能低于实际结果,因为它只计算那些被触摸过的对象。

使用ps或类似工具,您只能获得该进程分配的内存页数量。此数字正确,但:

不反映应用程序使用的实际内存量,只反映为其保留的内存量如果页面被共享,例如由多个线程共享或使用动态链接库共享,则可能会产生误导

如果您真的想知道应用程序实际使用的内存量,则需要在探查器中运行它。例如,Valgrind可以让您了解所使用的内存量,更重要的是,了解程序中可能的内存泄漏。Valgrind的堆轮廓仪工具称为“massif”:

Massif是一个堆分析器。它通过定期拍摄程序堆的快照来执行详细的堆分析。它会生成一个图表,显示一段时间内的堆使用情况,包括程序中哪些部分负责最多内存分配的信息。该图由文本或HTML文件补充,该文件包含更多信息,用于确定分配最多内存的位置。Massif运行程序的速度比正常速度慢20倍。

如Valgrind文档中所述,您需要通过Valgrind运行程序:

valgrind --tool=massif <executable> <arguments>

Massif写入内存使用快照的转储(例如Massif.out.1245)。这些快照提供(1)内存使用的时间线,(2)每个快照的程序内存分配位置的记录。分析这些文件的一个很好的图形工具是massif可视化工具。但我发现,与Valgrind一起提供的基于文本的简单工具ms_print已经有了很大的帮助。

要查找内存泄漏,请使用valgrind的(默认)memcheck工具。