Linux/Unix进程的最高内存使用率

486

是否有一种工具可以运行命令行并报告最高 RAM 使用总量?

我想象着类似于 /usr/bin/time 的东西。

20个回答

531

[编辑:适用于Ubuntu 14.04:/usr/bin/time -v command,请确保使用完整的路径。]

如果你在Ubuntu 8.10上使用/usr/bin/time并传递-v参数,似乎可以得到所需信息。例如,下面的输出中包含了最大常驻集大小

$ /usr/bin/time -v ls /
....
        正在计时的命令:"ls /"
        用户时间(秒):0.00
        系统时间(秒):0.01
        CPU使用率(百分比):250%
        经过的时间(墙钟)(h:mm:ss 或 m:ss):0:00.00
        平均共享文本大小(千字节):0
        平均未共享数据大小(千字节):0
        平均堆栈大小(千字节):0
        平均总大小(千字节):0
        最大常驻集大小(千字节):0
        平均常驻集大小(千字节):0
        主要(需要I/O)页面错误:0
        次要(回收帧)页面错误:315
        自愿上下文切换:2
        非自愿上下文切换:0
        页面交换:0
        文件系统输入:0
        文件系统输出:0
        发送的Socket消息:0
        接收的Socket消息:0
        已传递的信号:0
        页面大小(字节):4096
        退出状态:0

4
可能它总是返回0,因为ls没有做太多事情。尝试一个更需要CPU的命令。 - Jon Ericson
21
从man页面:time显示的大多数信息都是从wait3(2)系统调用中派生的。这些数字仅与wait3(2)返回的数字一样好。在没有返回状态信息的wait3(2)调用的系统上,会使用times(2)系统调用。然而,它提供的信息比wait3(2)少得多,因此在这些系统上,time将大多数资源报告为零。 - lothar
95
"bash: -v: command not found"的意思是bash截获了使用时间的命令。使用/bin/time -v可以解决这个问题。 - gcb
33
在 macOS 上尝试使用 time -l 命令,可以得到类似的输出结果。 - Volker Stolz
4
这种方法不够准确。每次我在Linux 3.19上运行一个完全确定性的程序时,都会得到不同的结果。 "最大驻留集大小"字段显然受到系统上其他正在运行的程序的影响。 - Vladimir Panteleev
显示剩余11条评论

99

(这是一个已经回答过的、古老的问题...但只是为了记录一下 :))

我受到Yang脚本的启发,设计了这个小工具,名为memusg。我将采样率增加到0.1以处理生命周期较短的进程。我不再监控单个进程,而是测量进程组的rss总和。(是的,我写了很多独立的程序来一起工作。)它目前支持Mac OS X和Linux。使用方法类似于time

memusg ls -alR / >/dev/null

目前它只显示峰值,但我对添加其他(粗略的)统计数据感兴趣。

有这样一个简单的工具,在开始任何严肃的性能分析之前,只需一瞥就能了解情况,非常好。


1
所有仍在使用PS的内容只能用来确定观察到的最高内存,而不是真正的最高内存。在一个时间间隔和另一个时间间隔之间,你总是可能会漏掉一些东西。 - gcb
7
memusg脚本的输出单位是什么?字节?千字节? - Daniel Standage
2
@DanielStandage:可能是以千字节为单位。它只是监视由ps -o rss=显示的值,其中rss是进程的实际内存(常驻集)大小(以1024字节为单位),这是从我的BSD手册中得到的信息。 - netj
3
@gcb:那又怎样,当你在测量样本时就会得到这样的结果。 - Volker Stolz
2
答案中给出的 memusg 链接似乎已经失效了。不过,/usr/bin/time 命令可以很好地完成这个任务。 - Tom Cornebize
显示剩余3条评论

78

Valgrind一行代码:

valgrind --tool=massif --pages-as-heap=yes --massif-out-file=massif.out ./test.sh; grep mem_heap_B massif.out | sed -e 's/mem_heap_B=\(.*\)/\1/' | sort -g | tail -n 1

注意使用--pages-as-heap来测量进程中的所有内存。更多信息请参见这里:http://valgrind.org/docs/manual/ms-manual.html

这会大大减慢命令的执行速度。


1
方便的脚本,但我需要在我的Slackware系统上使用“-g”排序(我假设您正在寻找最高值)。 - Nick Coleman
1
在CentOS 5.5发行版中,Valgrind-3.5.0缺少“--pages-as-heap”选项。此外,“--trace-children”也可能是Valgrind的有用选项。我不确定它的作用,但我猜测它也会跟踪子进程。 - NickSoft
3
+1 对于 valgrind --massif。你也可以使用附带的 ms_print 工具获取方便的输出(包括随时间变化的 ASCII 图表)。 - Eli Bendersky
9
Massif的开销比“time”要高得多,例如在像“ls”这样的命令上至少需要多花费10倍的时间。 - Timothy Gu
12
确实太庞大了。这个答案应该提到减速。我想要测量的命令通常需要35秒才能完成。我已经运行了这个valgrind命令半个多小时了,但它还没有完成... - unagi
显示剩余2条评论

77

在 Linux 上:

使用/usr/bin/time -v <program> <args>,并查找“最大常驻内存集大小”。

(不要与 Bash 中的time内置命令混淆!因此使用完整路径/usr/bin/time

例如:

> /usr/bin/time -v ./myapp
        User time (seconds): 0.00
        . . .
        Maximum resident set size (kbytes): 2792
        . . .

在BSD和MacOS中:

使用/usr/bin/time -l <program> <args>,查找"最大驻留集大小":

>/usr/bin/time -l ./myapp
        0.01 real         0.00 user         0.00 sys
      1440  maximum resident set size
      . . .

11
使用命令 sudo apt-get install time 安装 time 工具。 - Rolf
4
这个问题不是已经在两年前的回答中得到了解决吗?链接在这里:https://dev59.com/3HRA5IYBdhLWcg3w8SiJ#774601 - Charles Duffy

67

这是一行代码,不需要任何外部脚本或工具,也不需要您通过Valgrind或时间之类的其他程序启动进程,因此您可以将其用于任何已经运行的进程:

grep ^VmPeak /proc/$PID/status

(用您感兴趣的进程的PID替换$PID


20
如果我不了解PID呢?比如说程序只运行很短的时间(小于1秒)的情况下。 - diralik
14
"VmHWM: 峰值常驻集大小"可能更适合用来衡量内存使用情况(而不是包括许多其他内容的VmPeak)。 - jfs
3
@jfs 这取决于您想要了解什么。如果我没记错,VmPeak 是包括虚拟内存在内的最大总内存使用量,而 VmHWM 是峰值 RAM 使用量。因此,如果您想知道程序所请求的总内存量,请使用 VmPeak;如果您想知道程序在给定时间内实际使用的 RAM 量,请使用 VmHWM。 - erobertc
1
@diralik 如果您正在检查自己编写的程序,可以嵌入一行代码来查看“/proc/self/status”文件。 - Fileland
1
如果您的操作系统正在运行64位操作系统,则VmPeak不应该有太大影响。导致系统内存耗尽的是VmHWM。在实际RAM用尽之前,在64位操作系统上用尽虚拟内存是闻所未闻的。 - Mikko Rantalainen
显示剩余2条评论

41

也许(gnu) time(1) 已经满足你的需求了。例如:

$ /usr/bin/time -f "%P %M" command
43% 821248

但是其他性能分析工具可能会根据您的需求提供更准确的结果。


1
我似乎总是得到零,即使对于大型命令也是如此。 - jes5199
我得到了不同的变量结果,例如同一个程序中的400%0和0%0。也许应该运行更长时间以获得更精确的结果? - Liran Orevi
我不知道该提什么建议。上面的代码正是我运行历史记录中恰好有的一个latex命令所生成的。正如我所说,使用其他工具可以获得更准确的结果。 - Jon Ericson
2
这适用于至少CentOS(因此,我敢打赌也适用于RHEL)系统。%P提供无关的统计信息(%CPU),这取决于调度程序,因此相当可变。 - Blaisorblade
对我来说很奇怪,"time"命令必须使用精确路径运行,就像示例中一样,否则它将无法识别"-f"选项。 - Deleteman
2
@Deleteman:在使用“csh”时,“时间”是一种内置命令。如果您使用确切的路径,它将允许您运行外部命令。据我所知,只有GNU版本支持格式选项。 - Jon Ericson

22

在MacOS Sierra上使用:

/usr/bin/time -l commandToMeasure

您可以使用grep来获取您想要的内容。


6
我已经花了一个小时尝试使用Instruments.app和dtrace来获取系统完整性开启时的内存分析报告(无法关闭),而我只需要这个简单的命令。小提示:您可以使用 command time -l 而不是 /usr/bin/time -l,这将导致您的shell实际调用名为 time 的二进制文件而不是内置函数。(是的, command 不是一个占位符, command time 不同于 time.) - Jakub Arnold

19

/usr/bin/time也许是你想要的,实际上就像这样。

 /usr/bin/time --format='(%Xtext+%Ddata %Mmax)'

有关详细信息,请参见time(1)...


1
我似乎总是得到零,即使对于大的命令也是如此。 - jes5199
根据上面的评论,看起来在一些Linux系统上,time(1)可能会对内存报告产生问题。jes5199和Liran请注意。 - simon
在Ubuntu 16.04上,文本和数据为零,但最大值是非零的,并产生有意义的值。我对此感到满意。 - Stéphane Gourichon
我希望Mmax的含义是我们想要的......手册对此描述得有点简略。 - matanster

18
time -f '%M' <run_program>

2
输出结果以千字节为单位(可能是 kibibytes?)。请注意,在 bash 中,您需要指定完整路径,例如 /usr/bin/time,以避免使用不支持 -f 的内置 time 关键字。 - pcworld

16

如果该进程至少运行了几秒钟,您可以使用以下bash脚本,它将运行给定的命令行,然后向stderr输出峰值RSS(用其他您感兴趣的属性替换rss)。 它相对轻量级,并且在Ubuntu 9.04中包含的ps上适用于我(我不能这样说time)。

#!/usr/bin/env bash
"$@" & # Run the given command line in the background.
pid=$! peak=0
while true; do
  sleep 1
  sample="$(ps -o rss= $pid 2> /dev/null)" || break
  let peak='sample > peak ? sample : peak'
done
echo "Peak: $peak" 1>&2

2
这种方法的主要缺点是,如果进程在短时间内分配了大量内存(例如接近结束时),可能无法检测到。减少睡眠时间可能会有所帮助。 - vinc17
监视峰值内存使用的唯一方法是检查/proc/<pid>/status和行VmWHM(水高标记,表示峰值常驻内存使用),如果您只需要监视一个进程。如果您需要监视一组进程使用的总RAM,则必须使用内存cgroup并以这种方式读取状态。请注意,如果您的系统不支持“cgroupv2”,则只有“root”可以创建内存cgroup。任何基于采样/轮询的黑客都会错过峰值。 - Mikko Rantalainen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接