Python эквивалент PHP memory_get_usage()?
Я уже нашел следующий вопрос, но мне было интересно, есть ли более быстрый и грязный способ оценить, насколько много памяти интерпретатор python в настоящее время используется для моего script, который не полагается на внешние библиотеки.
Я прихожу из PHP и использовал memory_get_usage() и memory_get_peak_usage() для этой цели, и я надеялся найти эквивалент.
Ответы
Ответ 1
Простое решение для 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
Он возвращает текущий и максимальный размер резидентной памяти (что, вероятно, означает, что люди говорят о том, сколько оперативной памяти используется приложением). Его легко расширить, чтобы захватить другие фрагменты информации из файла /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
Ответ 2
Вы также можете использовать функцию getrusage()
из стандартного библиотечного модуля resource
. Полученный объект имеет атрибут ru_maxrss
, который дает общее использование памяти для вызывающего процесса:
>>> import resource
>>> resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
2656
Документы Python неясны в отношении единиц, но справочная страница Mac OS X для getrusage(2)
описывает единицы как килобайты.
Страница руководства Linux не ясна, но она, по-видимому, эквивалентна информации /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
для общего использования процесса (self и child).
Это будет охватывать случай memory_get_usage()
, но не включает пиковое использование. Я не уверен, что любые другие функции из модуля resource
могут дать пиковое использование.
Ответ 3
Принятые правила ответа, но может быть проще (и более переносимым) использовать psutil. Он делает то же самое и намного больше.
UPDATE: muppy также очень удобно (и гораздо лучше документировано, чем guppy/heapy).
Ответ 4
попробуйте heapy
Ответ 5
/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
Здесь статья автора memory_profiler, в которой объясняется, что 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()
Кроме того, здесь представлено очень понятное, но информативное исследование по сценарию авторов, в котором объясняется, что такое ядро, виртуальная и резидентная память, и как они взаимозависимы.