Python相当于PHP的memory_get_usage()?

时间:2009-05-22 13:49:42

标签: python

我已经found the following question,但我想知道是否有更快更脏的方法来估算python解释器当前用于我的脚本的内存量,而不依赖于外部库

我来自PHP,为了这个目的,我常常使用memory_get_usage()memory_get_peak_usage(),我希望找到一个等价物。

6 个答案:

答案 0 :(得分:31)

Linux和其他/proc/self/status系统的简单解决方案是以下代码,我在我的项目中使用该代码:

def memory_usage():
    """Memory usage of the current process in kilobytes."""
    status = None
    result = {'peak': 0, 'rss': 0}
    try:
        # This will only work on systems with a /proc file system
        # (like Linux).
        status = open('/proc/self/status')
        for line in status:
            parts = line.split()
            key = parts[0][2:-1].lower()
            if key in result:
                result[key] = int(parts[1])
    finally:
        if status is not None:
            status.close()
    return result

它返回当前和峰值驻留内存大小(这可能是人们在谈论应用程序使用多少RAM时的意思)。可以很容易地扩展它以从/proc/self/status文件中获取其他信息。

对于好奇:cat /proc/self/status的完整输出如下:

% cat /proc/self/status
Name:   cat
State:  R (running)
Tgid:   4145
Pid:    4145
PPid:   4103
TracerPid:      0
Uid:    1000    1000    1000    1000
Gid:    1000    1000    1000    1000
FDSize: 32
Groups: 20 24 25 29 40 44 46 100 1000 
VmPeak:     3580 kB
VmSize:     3580 kB
VmLck:         0 kB
VmHWM:       472 kB
VmRSS:       472 kB
VmData:      160 kB
VmStk:        84 kB
VmExe:        44 kB
VmLib:      1496 kB
VmPTE:        16 kB
Threads:        1
SigQ:   0/16382
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000000
SigCgt: 0000000000000000
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: ffffffffffffffff
Cpus_allowed:   03
Cpus_allowed_list:      0-1
Mems_allowed:   1
Mems_allowed_list:      0
voluntary_ctxt_switches:        0
nonvoluntary_ctxt_switches:     0

答案 1 :(得分:17)

您还可以使用标准库模块getrusage()中的resource函数。生成的对象具有属性ru_maxrss,该属性为调用进程提供总峰值内存使用量:

>>> import resource
>>> resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
2656

Python docs并不清楚单位究竟是什么,但getrusage(2)的{​​{3}}将单位描述为千字节。

Linux手册页不清楚,但它似乎等同于接受的答案中描述的/proc/self/status信息(即千字节)。对于与上述相同的过程,在Linux上运行,接受的答案中列出的函数给出:

>>> memory_usage()                                    
{'peak': 6392, 'rss': 2656}

这可能不像/proc/self/status解决方案那么容易使用,但它是标准库,因此(如果单位是标准的)它应该是跨平台的,并且可以在缺少{{的系统上使用1}}(例如Mac OS X和其他Unix,也许是Windows)。

此外,/proc/函数也可以getrusage()用于获取子进程的使用,并且(在某些系统上)resource.RUSAGE_CHILDREN用于总(自我和子)进程使用。< / p>

这将涵盖resource.RUSAGE_BOTH案例,但不包括峰值使用情况。我不确定memory_get_usage()模块中的任何其他函数是否可以提供峰值使用。

答案 2 :(得分:10)

接受的答案规则,但使用psutil可能更容易(也更便于移植)。它也做了同样的事情。

更新:muppy也非常方便(并且比guppy / heapy记录得更好。)

答案 3 :(得分:2)

尝试heapy

答案 4 :(得分:1)

/proc/self/status中也包含/proc/self/statm中相同类型的数据。但是,解析起来更容易,因为它只是一个用空格分隔的列表,其中包含多个statistics。我无法确定两个文件是否总是存在。

  

/ proc / [pid] / statm

     

提供有关内存使用情况的信息,以页为单位。                 列为:

     
      
  • 大小(1)程序总大小                            (与/ proc / [pid] / status中的VmSize相同)
  •   
  • 居民(2)居民集合大小                            (与/ proc / [pid] / status中的VmRSS相同)
  •   
  • 共享的(3)个常驻共享页面数(即由文件支持)                            (与/ proc / [pid] / status中的RssFile + RssShmem相同)
  •   
  • 文本(4)文本(代码)
  •   
  • lib(5)库(从Linux 2.6开始不使用;始终为0)
  •   
  • 数据(6)数据+堆栈
  •   
  • dt(7)脏页(自Linux 2.6起未使用;始终为0)
  •   

这是一个简单的例子:

from pathlib import Path
from resource import getpagesize

PAGESIZE = getpagesize()
PATH = Path('/proc/self/statm')


def get_resident_set_size() -> int:
    """Return the current resident set size in bytes."""
    # statm columns are: size resident shared text lib data dt
    statm = PATH.read_text()
    fields = statm.split()
    return int(fields[1]) * PAGESIZE


data = []
start_memory = get_resident_set_size()
for _ in range(10):
    data.append('X' * 100000)
    print(get_resident_set_size() - start_memory)

这会产生一个看起来像这样的列表:

0
0
368640
368640
368640
638976
638976
909312
909312
909312

您可以看到在大约分配了3个100,000字节后,它跳了约300,000字节。

答案 5 :(得分:0)

/proc/self/status具有以下相关密钥:

  • VmPeak :峰值虚拟内存大小。
  • VmSize :虚拟内存大小。
  • VmHWM :峰值驻留集大小(“高水位线”)。
  • VmRSS :常驻集大小。

因此,如果关注的是驻留内存,我可以使用以下代码来检索它:

def get_proc_status(keys = None):
    with open('/proc/self/status') as f:
        data = dict(map(str.strip, line.split(':', 1)) for line in f)

    return tuple(data[k] for k in keys) if keys else data

peak, current = get_proc_status(('VmHWM', 'VmRSS'))
print(peak, current)  # outputs: 14280 kB 13696 kB

这是一个article by memory_profiler's author,它解释了getrusage的{​​{1}}并不总是一个实用的衡量标准。另请注意,ru_maxrss可能与VmHWM不同(我在某些情况下看到ru_maxrss更大)。但在简单的情况下它们是相同的:

ru_maxrss

此外,这是一个非常易于理解但信息丰富的case study by atop authors,它解释了什么是内核,虚拟和驻留内存,以及它们如何相互依赖。