我已经 找到了以下问题,但我想知道是否有一种更快捷、更简便的方式来估计Python解释器当前正在使用多少内存来运行我的脚本,而不依赖于外部库。
我之前用PHP,习惯使用memory_get_usage()以及memory_get_peak_usage()来做这件事情,我希望能够找到一个相应的函数。
我已经 找到了以下问题,但我想知道是否有一种更快捷、更简便的方式来估计Python解释器当前正在使用多少内存来运行我的脚本,而不依赖于外部库。
我之前用PHP,习惯使用memory_get_usage()以及memory_get_peak_usage()来做这件事情,我希望能够找到一个相应的函数。
对于拥有/proc/self/status
的Linux和其他系统,以下代码是一个简单的解决方案,我在我的项目中使用它:
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
resource
模块中的getrusage()
函数。产生的对象有属性ru_maxrss
,它给出了调用进程的总峰值内存使用量:>>> import resource
>>> resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
2656
Python文档没有明确说明单位是什么,但Mac OS X man页面中getrusage(2)
的描述为千字节。
Linux man页面不够清晰,但它似乎等同于接受答案中描述的/proc/self/status
信息(即千字节)。对于上述相同的进程,在Linux上运行,接受答案中列出的函数给出:
>>> memory_usage()
{'peak': 6392, 'rss': 2656}
这种方法可能不像/proc/self/status
解决方案那样易于使用,但它是标准库,因此(如果单位是标准的)应该是跨平台的,并可用于缺少/proc/
(例如Mac OS X和其他Unix系统,也许是Windows)的系统。
此外,getrusage()
函数还可以给出resource.RUSAGE_CHILDREN
以获取子进程的使用情况,并且(在某些系统上)resource.RUSAGE_BOTH
表示总体(自身和子进程)进程使用情况。
这将涵盖memory_get_usage()
情况,但不包括峰值使用情况。我不确定resource
模块中是否有其他函数可以提供峰值使用情况。
35819520
,我相当确定它应该是35MB
而不是35GB
,所以看起来这应该是以字节为单位的。 :) - Kit Sunde/proc/self/status
有以下相关键:
因此,如果关注的是驻留内存,则可以使用以下代码来检索它:
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
getrusage
的ru_maxrss
并非总是实用的度量方式。同时需要注意的是,VmHWM
可能不同于ru_maxrss
(在某些情况下我看到ru_maxrss
更大)。但在简单情况下它们是相同的。import resource
def report():
maxrss = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
peak, current = get_proc_status(('VmHWM', 'VmRSS'))
print(current, peak, maxrss)
report()
s = ' ' * 2 ** 28 # 256MiB
report()
s = None
report()
/proc/self/status
中的数据与 /proc/self/statm
中的数据相同。但是,它更容易解析,因为它只是由几个以空格分隔的统计数据组成的列表。我无法确定这两个文件是否始终存在。
/proc/[pid]/statm
提供有关内存使用情况的信息,以页面为单位测量。列如下:
- size (1) 程序总大小(与/proc/[pid]/status中的VmSize相同)
- resident (2) 常驻集大小(与/proc/[pid]/status中的VmRSS相同)
- shared (3) 常驻共享页数(即由文件支持的页数)(与/proc/[pid]/status中的RssFile+RssShmem相同)
- text (4) 文本(代码)
- lib (5) 库(自Linux 2.6起未使用;始终为0)
- data (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