如何在Python中使用psutil获得程序的最大内存使用率

我正在使用下面的代码来获取该程序的最大内存使用量。

import os, subprocess , psutil def mem(cmd): try: with open('in.txt','r') as infile, open('out.txt', 'w') as outfile: p=psutil.Popen("./"+cmd,shell=False,stdin=infile,stdout = outfile) print p.memory_info() except Exception: print "Error" cmd=raw_input() mem(cmd) 

问题是有时初始运行的程序的内存使用量输出是(0,0),但随后显示正确的输出。 我不知道为什么发生这种情况。 对于一些程序,比如hello world程序在c ++中,输出是pmem(rss=4096, vms=315392) ,大概是0.3M(我认为输出是以字节为单位),但是在ideone.com上运行hello world程序,输出为〜3M。 为什么会有这种背叛?

cmd是可执行文件的名称。

命令的输出print subprocess.check_output(['ps', 'v', '-p', str(p.pid)])

PID TTY STAT TIME MAJFL TRS DRS RSS %MEM COMMAND 16150 pts/16 Z+ 0:00 0 0 0 0 0.0 [a.out] <defunct>

我的一个示例C ++程序:

 `int a[1000000]; int main() { return 0; }` 

有时会返回pmem(rss = 4096,vms = 4313088),有时会返回pmem(rss = 0,vms = 0)

<defunct>意味着子进程是一个僵尸进程 (它已经死了,但是它的状态还没有被父p.poll()读取( p.poll()或者p.wait() ))。 似乎psutilps显示这些进程的RSS为零。

结果取决于子p.memory_info()是否会比p.memory_info()更早退出。 这是一场比赛。 如果在C ++程序的出口处添加延迟,则可能会在子p.memory_info()退出之前调用p.memory_info()并且应该得到非零的结果。

问题是我可以得到任意程序来评估。 语言也是不固定的。 这个问题没有一个优雅的解决方案吗?

即使在退出之后,您也可能需要操作系统支持来保存有关子进程内存使用情况的信息。 或者你可以使用内存分析器(如valgrind运行程序并读取其结果。 要收集结果:

 $ valgrind --tool=massif cmd arg1 arg2 

要查看结果,可以使用ms_print

 $ ms_print massif.out.* | less 

或者GUI Massif-Visualizer

@mdadm提出了一个更简单的解决方案: time命令 :

 from subprocess import Popen, PIPE p = Popen(['time', '-f', '%M'] + args, stderr=PIPE) ru_maxrss = int(p.communicate()[1]) print("Maximum rss %d KB" % ru_maxrss) 

GNU时间使用wait3()填充资源使用信息(如果可用)。 它可以在Python中调用:

 import os from subprocess import Popen p = Popen(args) ru = os.wait4(p.pid, 0)[2] print("Maximum rss %d KB" % ru.ru_maxrss) 

我比较了psutil.Process.memory_info (rss)返回的最大值与ru_maxrss返回的ru_maxrss值以及valgrind --tool=massif报告的最大内存总量: 它们是相似的

也可以看看:

  • 一种确定进程的“真实”内存使用情况的方法,即私人脏RSS?
  • 在Linux中如何报告内存使用情况?
  • 查找在命令行中指定的进程所消耗的最大内存。

这里的问题是,psutils从/ proc文件系统获取快照,就像你在源文件中看到的一样。

当你运行hello world的例子时,在某些情况下,它会在python有机会读取/ proc的值之前结束。

一旦这个过程完成,它实际上不再消耗任何内存。 你可以用strace来确认。

 open("/proc/13420/statm", O_RDONLY) = 3 read(3, "0 0 0 0 0 0 0\n", 1024) = 14 

如果你修改你的例子来使用类似睡眠的东西,你会注意到psutils一直给内存使用回来。

 #include <iostream> #include <unistd.h> int main() { std::cout << "Hello World.. sleeping!"; sleep(3); } 

你的python脚本的输出…

 a.out meminfo(rss=286720, vms=12931072) 

一个简单的方法来完成你想要做的事情,就是使用/ usr / bin / time命令,在大多数平台上它会给你启动的进程的平均内存使用量,或者像JF Sebastian所说的那样使用valgrind。当我正在研究和测试我的答案时发布了这些内容)

 Hello World.. sleeping!0.00user 0.00system 0:03.00elapsed 0%CPU (0avgtext+0avgdata 1144maxresident)k 0inputs+0outputs (0major+348minor)pagefaults 0swaps