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

时间:2014-03-29 15:21:26

标签: python unix python-2.7 memory

我使用以下代码来获取程序的最大内存使用量。

    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),但随后显示正确的输出。我不知道为什么会这样。对于某些程序,例如c ++中的hello world程序,输出为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)

2 个答案:

答案 0 :(得分:3)

这里的问题是psutils从/ proc文件系统快速获取快照,正如您在source中看到的那样。

当你运行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命令,该命令在大多数平台上将为您提供启动过程的平均总内存使用量或使用valgrind作为JF Sebastian建议......当我正在研究和测试我的答案时发布了谁;)

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

答案 1 :(得分:1)

<defunct>表示子流程为zombie process(它已经死了,但父级尚未读取其状态(p.poll()p.wait()))。对于此类流程,似乎psutilps都显示RSS为零。

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

  

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

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

$ valgrind --tool=massif cmd arg1 arg2 

要查看结果,您可以使用ms_print

$ ms_print massif.out.* | less

或GUI Massif-Visualizer

@mdadm suggested更简单的解决方案:time command

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返回的os.wait4值以及valgrind --tool=massif报告的最大总内存进行了比较:他们很相似

另见: