我正在使用下面的代码来获取该程序的最大内存使用量。
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()
))。 似乎psutil
和ps
显示这些进程的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
报告的最大内存总量: 它们是相似的 。
也可以看看:
这里的问题是,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