ChatGPT解决这个技术问题 Extra ChatGPT

如何测量应用程序或进程的实际内存使用情况?

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

Understanding memory usage on Linux 的博客文章中,ps 不是用于此意图的准确工具。

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

(注意:这个问题在here中有详细介绍。)

这个问题现在可能属于 serverfault.com,尽管它告诉我它“太旧而无法迁移”。但实际上并不想关闭它...
实际上 ps 甚至没有显示 - 它显示虚拟和常驻内存编号,其中 virtual 是进程理论上可以使用的最大内存量,它是唯一的进程(从来没有),使用了它分配的每一页(永远不会发生)并且没有映射或取消映射任何页面(不太可能)。而 resident 显示现在有多少虚拟内存映射到物理内存。通常 virt > usage > res 但在 64 位系统上 virt ~= res*10 它的范围非常广泛。
链接文章的摘录完全是胡说八道。 RSS 是实际使用的物理内存,即使进程是唯一运行的进程,VSZ 也可能会或可能不会转换为物理内存使用。

P
Peter Mortensen

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

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

如果页面是共享的,例如通过多个线程或通过使用动态链接库,可能会产生误导

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

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

Valgrind documentation 中所述,您需要通过 Valgrind 运行程序:

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

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

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


要解释 valgrind 生成的结果,我可以推荐 alleyoop。它并不太花哨,它只是告诉您定位泄漏源所需知道的内容。一对不错的实用程序。
(a) 项是正确的。使用的页面和应用程序通过调用 malloc()、new 等实际分配的内存之间存在差异。驻留使用仅显示有多少分页内存驻留在 RAM 中。
这并没有真正说明如何使用 valgrind 获取内存使用情况?
默认的 valgrind 工具 memcheck 可用于检测内存泄漏,但它并不是真正的内存分析器。为此,您需要 valgrind --tool=massif。
@DavidSchwartz 我看不出你的陈述与我的矛盾。我有一种感觉,你太在意我的观点是“错误的”,而不是真正阅读我所说的话。我在这里的全部观点是,RSS 是衡量应用程序实际内存使用情况的不恰当措施,您在最后两句话中提出了同样的观点。真的,你认为我首先提出 RSS 收缩的原因是什么?所以你把它拼出来给我证明我所指的确切内容是“错误的”?你对我的态度令人厌烦。
H
Harikrishnan

尝试 pmap 命令:

sudo pmap -x <process pid>

使用 sudo 运行,否则不会出现错误并且不显示内存消耗。
在 OSX 上不存在(对于从谷歌来到这里的任何人)
这是对问题的完整答案!附言。在我的 shell 中,pmap 可以在没有 sudo 的情况下读取进程。
Re OS X(似乎不是OP的关注点),您可以使用 vmmap(1) 看到一些类似的数据
根据 pmap,我非常简单的 Java Spring Boot 应用程序使用 20 GB 内存。我不认为这是正确的。
P
Peter Mortensen

很难确定,但这里有两个“接近”的东西可以提供帮助。

$ 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

我错过了什么吗?该问题询问如何更好地测量进程的内存使用情况,因为 ps 中报告的 VSZ 和 RSS 具有误导性。您的回答详细说明了如何查找 VSZ - 与被提及的具有误导性的值相同。
@thomasrutter 是的,您错过了原始问题(第 1 版),它已被多次编辑并且已经很旧(2008 年)。最初的问题只是询问如何测量进程的内存使用情况。不过,如果内容已过时,请随意编辑问题和答案。 :)
注意:给出与 gnome-system-monitor 完全不同的答案
P
Peter Mortensen

在最新版本的 Linux 中,使用 smaps 子系统。例如,对于 PID 为 1234 的进程:

cat /proc/1234/smaps

它会准确地告诉你它当时使用了多少内存。更重要的是,它将内存划分为私有和共享,因此您可以知道您的程序实例正在使用多少内存,而不包括程序的多个实例之间共享的内存。


我猜 pmap 是一个更简单的界面。
这个答案对于没有 pmap 的嵌入式系统来说是黄金
这提供了大量信息。我可以用什么来获取正在使用的实际总 RAM?
P
Peter Mortensen

没有任何简单的方法可以计算这一点。但有些人试图得到一些好的答案:

ps_mem.py

GitHub 上的 ps_mem.py


nice 输出一个干净的内存和进程列表
非常好,非常聪明的分组。
是的,确实不错。我发现 ps_memsmem 对于最终用户测量非常有用,例如。 pmap 的非常详细的输出面向开发人员...允许检索 Firefox 的每个字体、插件、库的内存使用情况,例如。谢谢大家。 @Bash,@thomasruther。
这是迄今为止唯一一个与 gnome-system-monitor 的输出相匹配的
P
Peter Mortensen

使用 smem,它是 ps 的替代方法,它计算每个进程的 USS 和 PSS。你可能想要PSS。

USS - 独特的套装尺寸。这是该进程独有的非共享内存量(将其视为唯一内存的 U)。它不包括共享内存。因此,这将低估进程使用的内存量,但当您想忽略共享内存时,它会很有帮助。

PSS - 比例集大小。这就是你想要的。它将唯一内存 (USS) 与其共享内存的一部分除以共享该内存的进程数相加。因此,它将为您提供每个进程正在使用多少实际物理内存的准确表示 - 共享内存真正表示为共享。想想 P 代表物理内存。

这与 ps 和其他实用程序报告的 RSS 相比如何:

RSS - 驻留集大小。这是每个进程使用的共享内存加上非共享内存的数量。如果任何进程共享内存,这将过度报告实际使用的内存量,因为相同的共享内存将被多次计算 - 再次出现在共享相同内存的每个其他进程中。因此,它相当不可靠,尤其是当高内存进程有很多分叉时——这在服务器中很常见,比如 Apache 或 PHP (FastCGI/FPM) 进程。

注意:smem 还可以(可选)输出饼图等图形。海事组织你不需要任何这些。如果您只想像使用 ps -A v 一样从命令行使用它,那么您不需要安装 Python 和 Matplotlib 推荐的依赖项。


关于 RSS 的一个关键点是,如今大多数应用程序共享大量代码页。每个共享库(例如 libc 和 libstdc++)都将被计算为每个使用它的进程。如果一个进程有多个实例正在运行,那么所有这些代码都将被重复计算。
准确地说,这就是为什么 RSS 会过度报告每个进程的实际物理内存。
smem 是我需要的。通过在每次启动新流程实例时使用 -t 运行它,我可以看到每个实例消耗的内存。对于铬: smem -t -P '/opt/google/chrome'
TL;DR:USS = 如果进程被杀死,将释放的物理内存量,PSS = 如果没有现有进程将被杀死,则此进程需要从系统获得的物理内存量,RSS = 可访问的物理内存量这个过程(但并不总是独占访问)。
@ZN13 我想知道同样的事情并最终运行 smem -k,它在数字后打印一个单位。
P
Peter Mortensen
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

以 root 身份使用它,您可以获得每个进程的内存使用情况的清晰输出。

输出示例:

     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]

有什么方法可以过滤列表,以便只有在 30 秒内使用超过 25% 内存的进程?我正在尝试查看运行过程,例如使用 PHPEclipse 调试器时的 Chrome 浏览器。
那个过滤器会很棒
我会尽快发布。
伟大的!但是循环应该从 x=2 开始,同时输出 pid 和 user。
如何在输出中获得PID?
P
Peter Mortensen

使用 time

不是 Bash 内置 time,而是您可以使用 which time 找到的那个,例如 /usr/bin/time

以下是它在一个简单的 ls 上所涵盖的内容:

$ /usr/bin/time --verbose ls
(...)
Command being timed: "ls"
User time (seconds): 0.00
System time (seconds): 0.00
Percent of CPU this job got: 0%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.00
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 2372
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 1
Minor (reclaiming a frame) page faults: 121
Voluntary context switches: 2
Involuntary context switches: 9
Swaps: 0
File system inputs: 256
File system outputs: 0
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0

我也是。这是我用来在 powercron.eu 中分析任务的方式 :)
brew install gnu-time 如果您使用的是 macOS,请使用 gtime
缺点:在进程完成执行之前不会得到结果。不能用于实时监控正在运行的进程。
/usr/bin/time -f '%M'
您也可以使用 \time 调用它(带有反斜杠以防止使用 shell 的内部时间)。
C
Community

这是对工具和问题的出色总结:archive.org link

我会引用它,以便更多的开发人员真正阅读它。

如果要分析整个系统的内存使用情况或彻底分析一个应用程序的内存使用情况(而不仅仅是它的堆使用情况),请使用 exmap。对于整个系统分析,找到具有最高有效使用率的进程,它们在实践中占用最多的内存,找到具有最高可写使用率的进程,它们创建的数据最多(因此可能泄漏或在数据使用方面非常无效)。选择这样的应用程序并在第二个列表视图中分析其映射。有关详细信息,请参阅 exmap 部分。还可以使用 xrestop 检查 X 资源的高使用率,尤其是在 X 服务器的进程占用大量内存的情况下。有关详细信息,请参阅 xrestop 部分。如果您想检测泄漏,请使用 valgrind 或可能的 kmtrace。如果您想分析应用程序的堆(malloc 等)使用情况,请在 memprof 或使用 kmtrace 中运行它,分析应用程序并搜索函数调用树以获得最大分配。有关更多详细信息,请参阅他们的部分。


exmap 于 2006 年被废弃且未构建
P
Peter Mortensen

除了答案中列出的解决方案之外,您还可以使用 Linux 命令“top”。它提供了正在运行的系统的动态实时视图,并以百分比的形式提供了整个系统以及每个程序的 CPU 和内存使用情况:

top

按程序 PID 过滤:

top -p <PID>

按程序名称过滤:

top | grep <PROCESS NAME>

“top”还提供了一些字段,例如:

VIRT -- Virtual Image (kb):任务使用的虚拟内存总量

RES——驻留大小(kb):任务已使用的非交换物理内存; RES = 代码 + 数据。

DATA - 数据+堆栈大小 (kb):专用于可执行代码以外的物理内存量,也称为“数据驻留集”大小或 DRS。

SHR -- Shared Mem size (kb):任务使用的共享内存量。它只是反映可能与其他进程共享的内存。

参考 here


谢谢,这就是我要找的东西;)
P
Peter Mortensen

对此没有单一的答案,因为您无法准确指出进程使用的内存量。 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 可能会给你足够的内存使用信息at。另一方面,Valgrind 将使您更好地了解程序整个生命周期的内存使用情况。


我试图找出一个进程在虚拟机上占用了多少内存,并想用它来设置 kubernetes 中的内存限制,我同意这个答案,所以将使用 pmap 显示的内存
C
CashCow

如果您的代码使用 C 或 C++ 编写,您可以使用 getrusage(),它会返回有关您的进程的内存和时间使用情况的各种统计信息。

并非所有平台都支持这一点,并且将为内存使用选项返回 0 值。

相反,您可以查看在 /proc/[pid]/statm 中创建的虚拟文件(其中 [pid] 被您的进程 ID 替换。您可以从 getpid() 获得)。

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


请注意,并非所有平台都支持此功能。
根据 Linux 手册页 (linux.die.net/man/2/getrusage),getrusage 是 SVr4、4.3BSD 和 POSIX.1-2001 规范的一部分(注意 POSIX 只指定了 utime 和 stime 字段。)我不希望它适用于非 UNIX 平台(可能除了通过像 Cygwin 这样为其他平台提供 UNIX 功能的环境。)
@大卫C。 OP正在询问Linux。
@CashCow,您的意思是 getpid(),因为我不知道 Linux 下 C/C++ 中的 getprocessid() 函数。
P
Peter Mortensen

我正在使用 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
=============================================

ps_mem 看起来不错,并且在 CentOS 上也可用 :-)
这个脚本绝对是惊人的。正是我需要的。如果需要,您可以使用这个长而简单的命令在 ubuntu 上快速轻松地获取它:sudo curl -sL https://raw.githubusercontent.com/pixelb/ps_mem/master/ps_mem.py -o /usr/local/bin/ps_mem.py; sudo chmod 755 /usr/local/bin/ps_mem.py; sudo apt install python -y -qq; sudo ps_mem.py
P
Paul Roub

另外三种方法可以尝试:

ps aux --sort pmem 它按 %MEM 对输出进行排序。 ps辅助| awk '{打印 $2, $4, $11}' |排序-k2r | head -n 15 它使用管道进行排序。 top -a 它开始按 %MEM 排序

(摘自 here


top 并且可能其他人没有准确表示进程实际使用的内存。例如,我有 64GiB 的 RAM,我有 10 个 postgres 进程,每个进程报告 16GiB RES 和 25% MEM。当然,他们不可能都使用 25%……每个人也有 15GiB SHR,而且似乎他们正在共享。
这如何回答这个问题?前提是:“ps 不是用于此意图的准确工具。”
P
Peter Mortensen

Valgrind 可以显示详细信息,但它会显着降低目标应用程序的速度,并且大多数情况下它会改变应用程序的行为。

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

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

马匿名映射内存

.p 私有 .d 脏 == malloc/mmapped 堆和堆栈分配和写入内存 .c clean == malloc/mmapped 堆和堆栈内存一旦分配、写入、然后释放,但尚未回收

.d 脏 == malloc/mmapped 堆和堆栈分配和写入的内存

.c clean == malloc/mmapped 堆和堆栈内存一旦分配、写入、然后释放,但尚未回收

.s 共享 .d 脏 == malloc/mmaped 堆可以在写入时复制并在进程之间共享(已编辑) .c clean == malloc/mmaped 堆可以在写入时复制并在进程之间共享(已编辑)

.d 脏 == malloc/mmaped 堆可以在写入时复制并在进程之间共享(已编辑)

.c clean == malloc/mmaped 堆可以在写入时复制并在进程之间共享(已编辑)

Mn 命名映射内存

.p 私有 .d 脏 == 文件 mmapped 写入内存 私有 .c clean == 映射程序/库文本 私有映射

.d 脏 == 文件映射写入内存私有

.c clean == 映射程序/库文本私有映射

.s 共享 .d 脏 == 文件 mmapped 写入内存 共享 .c clean == 映射库文本 共享映射

.d 脏 == 文件映射写入内存共享

.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

p
pokute
#!/bin/ksh
#
# Returns total memory used by process $1 in kb.
#
# See /proc/NNNN/smaps if you want to do something
# more interesting.
#

IFS=$'\n'

for line in $(</proc/$1/smaps)
do
   [[ $line =~ ^Size:\s+(\S+) ]] && ((kb += ${.sh.match[1]}))
done

print $kb

ksh 是标准外壳。它可能不会默认安装在 linux 发行版上,供桌面用户使用或用于简约目的,但在几乎任何 unix-/linux 操作系统中只需一个命令即可。 (即在所有 BSD、所有真正的 UNIX、RHEL、SLES、Debian、Ubuntu、OSX 上)
默认情况下,该文件只能由 root 用户访问。
以下只是将上述内容重写为 sed | awk 并在 Busybox v1.23.2 中工作:sed -n 's/^Size:\s\+\(\S\+\) .*/\1/p' /proc/$1/smaps | awk '{s+=$1} END {print s}'
@Catskul - POSIX 标准将其标准 shell 指定为 Korn shell 的严格子集,这是 Bourne shell 的增强版本。
P
Peter Mortensen

我正在使用 htop;这是一个非常好的控制台程序,类似于 Windows Task Manager


我使用了 htop 并且比 top 更好,但它仍然会向您显示来自不同应用程序的所有线程,而不会将它们分组,使其几乎与 top 一样无用。
$ htop -p $(pgrep <你的进程名> | xargs | tr ' ' ',')
P
Peter Mortensen

获取Valgrind。让它运行你的程序,它会告诉你很多关于它的内存使用情况。

这仅适用于程序运行一段时间并停止的情况。我不知道 Valgrind 是否可以处理已经运行的进程,或者不应该停止进程,例如守护进程。


不,不可能将 valgrind “附加”到正在运行的进程。这是设计使然。
P
Peter Mortensen

更“真实世界”使用情况的一个很好的测试是打开应用程序,运行 vmstat -s,然后检查“活动内存”统计信息。关闭应用程序,等待几秒钟,然后再次运行 vmstat -s

然而,应用程序显然正在使用释放的大量活动内存。


这比ps好多少?它带有 ps 的所有限制,而且更加不准确......
一个典型的 Unix 系统总是有许多进程开始和结束。您无法预测您的可用 RAM。
P
Peter Mortensen

下面的命令行将为您提供在 Linux 机器上运行的各种进程使用的总内存,以 MB 为单位:

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 "" }' | awk '{total=total + $1} END {print total}'

P
Peter Mortensen

如果进程没有使用太多内存(或者是因为您希望会出现这种情况,或者其他一些命令已经给出了这个初始指示),并且该进程可以承受短时间的停止,您可以尝试使用 gcore 命令。

gcore <pid>

检查生成的核心文件的大小,以了解特定进程正在使用多少内存。

如果进程使用数百兆字节或千兆字节,这将不会很好地工作,因为根据 I/O 性能创建核心生成可能需要几秒钟或几分钟。在核心创建过程中,进程会停止(或“冻结”)以防止内存更改。所以要小心。

还要确保生成核心的挂载点有足够的磁盘空间,并且系统不会对在该特定目录中创建的核心文件做出负面反应。


P
Peter Mortensen

注意:这只有在内存消耗增加时才能 100% 正常工作

如果您想监视给定进程(或一组已处理的共享公用名,例如 google-chrome)的内存使用情况,您可以使用我的 bash 脚本:

while true; do ps aux | awk ‚{print $5, $11}’ | grep chrome | sort -n > /tmp/a.txt; sleep 1; diff /tmp/{b,a}.txt; mv /tmp/{a,b}.txt; done;

这将不断寻找变化并打印出来。

https://i.stack.imgur.com/0g9yT.png


S
Skynet

如果您想要比使用 Valgrind 进行分析更快的东西并且您的内核较旧并且您不能使用 smaps,那么带有选项的 ps 可以显示进程的驻留集(使用 ps -o rss,command)可以为您提供快速合理的 {2 } 实际使用的非交换内存量。


A
Alexis Wilke

我建议你使用顶部。您可以在 this page 上找到有关它的所有信息。它能够为您的流程提供所有必要的 KPI,还可以捕获到文件中。


要显示 PSIZE [“此进程(或用户)的比例内存大小] 使用 atop -R 在顶部启动。要显示每个用户的摘要推送 p,按内存使用情况排序,从顶部推送“M”。这给出与 smem 相似的数字。
在这种情况下,什么是“KPI”?
P
Peter Mortensen

在这里再次投票给 Valgrind,但我想补充一点,您可以使用像 Alleyoop 这样的工具来帮助您解释 Valgrind 生成的结果。

我一直使用这两个工具,并且总是有精益、无泄漏的代码来自豪地展示它;)


P
Peter Mortensen

查看此 shell 脚本以检查 memory usage by application in Linux

它也是 available on GitHub 并且在版本 without paste and bc 中。


P
Peter Mortensen

虽然这个问题似乎是关于检查当前正在运行的进程,但我想查看应用程序从头到尾使用的峰值内存。除了Valgrind,您还可以使用tstime,它更简单。它测量“高水位”内存使用情况(RSS 和虚拟)。从this answer


大多数应用程序——即那些使用 malloc() 和类似 malloc 的内存库的应用程序——在进程终止之前不会将页面返回给操作系统。因此,您使用 PS(或任何其他不深入进程堆的工具)看到的数量将是高水位线。
在这种情况下,什么是“RSS”?
S
Sruli

鉴于一些答案(感谢 thomasrutter),为了获得单个应用程序的实际交换和 RAM,我想出了以下内容,假设我们想知道“firefox”正在使用什么

sudo smem | awk '/firefox/{swap += $5; pss += $7;} END {print "swap = "swap/1024" PSS = "pss/1024}'

或者对于 libvirt;

sudo smem | awk '/libvirt/{swap += $5; pss += $7;} END {print "swap = "swap/1024" PSS = "pss/1024}'

这将为您提供以 MB 为单位的总数,如下所示;

swap = 0 PSS = 2096.92

swap = 224.75 PSS = 421.455

在 ubuntu 16.04 到 20.04 上测试。


thomasrutter's answer 中使用了“smem”。
P
Peter Mortensen

基于对 a related question 的回答。

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

要求:

运行该进程的设备应已安装并运行 snmp

snmp 应配置为接受来自您将运行以下脚本的请求(可以在文件 snmpd.conf 中配置)

您应该知道要监控的进程的进程 ID (PID)

笔记:

HOST-RESOURCES-MIB::hrSWRunPerfCPU 是该进程消耗的系统总 CPU 资源的厘秒数。请注意,在多处理器系统上,该值可能会在 1 厘秒的实际(挂钟)时间内增加超过 1 厘秒。

HOST-RESOURCES-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

P
Peter Mortensen

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