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