Python-эквивалент PHP memory_get_usage ()? - PullRequest
24 голосов
/ 22 мая 2009

Я уже нашел следующий вопрос , но мне было интересно, есть ли более быстрый и более грязный способ получить оценку того, сколько памяти интерпретатор Python использует в настоящее время для моего сценария, который не ' не полагайтесь на внешние библиотеки.

Я пришел из PHP и использовал memory_get_usage () и memory_get_peak_usage () много для этой цели, и я надеялся найти эквивалент.

Ответы [ 6 ]

31 голосов
/ 22 мая 2009

Простым решением для 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
17 голосов
/ 06 октября 2011

Вы также можете использовать функцию 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 и другие Unixes, может быть, Windows).

Кроме того, функция getrusage() также может быть предоставлена ​​resource.RUSAGE_CHILDREN для получения использования для дочерних процессов и (в некоторых системах) resource.RUSAGE_BOTH для общего (собственного и дочернего) использования процесса.

Это будет охватывать случай memory_get_usage(), но не включает пиковое использование. Я не уверен, что другие функции из модуля resource могут дать пиковое использование.

10 голосов
/ 16 октября 2012

Принимаются правила ответа, но может быть проще (и более переносимо) использовать psutil . Он делает то же самое и многое другое.

ОБНОВЛЕНИЕ: muppy также очень удобно (и намного лучше задокументировано, чем гуппи / куча).

2 голосов
/ 22 мая 2009

попробуй куча

1 голос
/ 26 ноября 2018

Те же данные, что и в /proc/self/status, также в /proc/self/statm. Тем не менее, его легче разобрать, потому что это просто список с разделителями-пробелами из нескольких статистических данных . Я не смог определить, присутствуют ли оба файла всегда.

/ Proc / [PID] / statm

Предоставляет информацию об использовании памяти, измеряемую в страницах. Столбцы:

  • размер (1) общий размер программы (аналогично VmSize в / proc / [pid] / status)
  • размер резидента (2) (аналогично VmRSS в / proc / [pid] / status)
  • shared (3) количество резидентных общих страниц (т. Е. С файлом) (аналогично RssFile + RssShmem в / proc / [pid] / status)
  • текст (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

Вы видите, что он увеличивается примерно на 300 000 байтов после примерно 3 выделений по 100 000 байтов.

0 голосов
/ 27 октября 2016

/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()

Кроме того, вот очень понятное, но информативное тематическое исследование поверх авторов , которое объясняет, что такое ядро, виртуальная и резидентная память и как они взаимозависимы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...