Как проверить использование памяти в iPython?

Я использую iPython для запуска моего кода. Интересно, есть ли какой-либо модуль или команда, которая позволит мне проверить использование памяти в памяти. Например:

In [1]: a = range(10000)
In [2]: %memusage a
Out[2]: 1MB

Что-то вроде %memusage <object> и вернуть память, используемую объектом.

Duplicate

Узнайте, сколько памяти используется объектом в Python

Ответ 1

К сожалению, это невозможно, но есть несколько способов аппроксимации ответа:

  • для очень простых объектов (например, ints, строк, float, double), которые представлены более или менее как простые типы языка C, вы можете просто вычислить количество байтов, как с помощью Решение Джона Малдера.

  • Для более сложных объектов хорошим приближением является сериализация объекта в строку с помощью cPickle.dumps. Длина строки - хорошее приближение объема памяти, необходимой для хранения объекта.

Существует одна большая проблема с решением 2, которая состоит в том, что объекты обычно содержат ссылки на другие объекты. Например, dict содержит строковые ключи и другие объекты в качестве значений. Эти другие объекты могут быть разделены. Поскольку pickle всегда пытается выполнить полную сериализацию объекта, он всегда будет чрезмерно оценивать объем памяти, необходимый для хранения объекта.

Ответ 2

Если вы используете массив numpy, вы можете использовать атрибут ndarray.nbytes для оценки его размера в памяти:

from pylab import *   
d = array([2,3,4,5])   
d.nbytes
#Output: 32

Ответ 3

UPDATE: еще один, возможно, более тщательный рецепт для оценки размера объекта python.

Вот поток, рассматривающий аналогичный вопрос

Предлагаемое решение состоит в том, чтобы написать свой собственный... используя некоторые оценки известного размера примитивов, служебных данных объекта python и размеров встроенных типов контейнеров.

Так как код не так длинный, вот прямая его копия:

def sizeof(obj):
    """APPROXIMATE memory taken by some Python objects in 
    the current 32-bit CPython implementation.

    Excludes the space used by items in containers; does not
    take into account overhead of memory allocation from the
    operating system, or over-allocation by lists and dicts.
    """
    T = type(obj)
    if T is int:
        kind = "fixed"
        container = False
        size = 4
    elif T is list or T is tuple:
        kind = "variable"
        container = True
        size = 4*len(obj)
    elif T is dict:
        kind = "variable"
        container = True
        size = 144
        if len(obj) > 8:
            size += 12*(len(obj)-8)
    elif T is str:
        kind = "variable"
        container = False
        size = len(obj) + 1
    else:
        raise TypeError("don't know about this kind of object")
    if kind == "fixed":
        overhead = 8
    else: # "variable"
        overhead = 12
    if container:
        garbage_collector = 8
    else:
        garbage_collector = 0
    malloc = 8 # in most cases
    size = size + overhead + garbage_collector + malloc
    # Round to nearest multiple of 8 bytes
    x = size % 8
    if x != 0:
        size += 8-x
        size = (size + 8)
    return size

Ответ 4

для общего размера локалей (в МБ):

from sys import getsizeof
sum([getsizeof(k) for k in locals().keys()])/10**6

Ответ 5

Я пытался понять, как сделать это для себя. Я попробовал несколько решений на этой странице и других страницах. Затем я провел некоторый поиск и наткнулся на https://ipython-books.github.io/44-profiling-the-memory-usage-of-your-code-with-memory_profiler/, который, кажется, дает альтернативное решение. Суть решения: используйте %mprun в ipython.

  1. Создайте функцию в физическом файле, скажем, memscript.py (важно: % mprun можно использовать только для функций, определенных в физических файлах). Создайте рассматриваемый объект в функции, например:
%%writefile memscript.py
def my_func():
    # create the object, e.g.
    a = [*range(10000)]

  1. Запуск
from memscript import my_func
%mprun -T mprof0 -f my_func my_func()

который генерирует файл mprof0. Содержимое также отображается:

Line #    Mem usage    Increment   Line Contents
================================================
     1     95.1 MiB     95.1 MiB   def my_func():
     2     97.8 MiB      2.7 MiB       a = [*range(100000)]

Из строки в строке 2 мы знаем, что память, используемая a, составляет 2,7 МБ. Я не уверен, насколько он точен, поскольку, когда я пытаюсь a = [*range(10000)], инермент равен 0!