Объем памяти в структуре Python
Существует ли ссылка на объем памяти структуры данных Python на 32- и 64-битных платформах?
Если нет, было бы неплохо иметь его на SO. Чем полнее, тем лучше! Итак, сколько байтов используется следующими структурами Python (в зависимости от len
а тип контента при необходимости)?
int
float
- ссылка
str
- строка в кодировке Юникод
tuple
list
dict
set
array.array
numpy.array
deque
- объект классов нового стиля
- объект классов старого стиля
- ... и все, что я забыл!
(Для контейнеров, которые хранят только ссылки на другие объекты, мы, очевидно, не хотим подсчитывать размер самого элемента, поскольку он может использоваться совместно.)
Кроме того, есть ли способ получить память, используемую объектом во время выполнения (рекурсивно или нет)?
6 ответов
Рекомендация из предыдущего вопроса заключалась в том, чтобы использовать sys.getsizeof (), цитируя:
>>> import sys
>>> x = 2
>>> sys.getsizeof(x)
14
>>> sys.getsizeof(sys.getsizeof)
32
>>> sys.getsizeof('this')
38
>>> sys.getsizeof('this also')
48
Вы могли бы принять этот подход:
>>> import sys
>>> import decimal
>>>
>>> d = {
... "int": 0,
... "float": 0.0,
... "dict": dict(),
... "set": set(),
... "tuple": tuple(),
... "list": list(),
... "str": "a",
... "unicode": u"a",
... "decimal": decimal.Decimal(0),
... "object": object(),
... }
>>> for k, v in sorted(d.iteritems()):
... print k, sys.getsizeof(v)
...
decimal 40
dict 140
float 16
int 12
list 36
object 8
set 116
str 25
tuple 28
unicode 28
2012-09-30
Python 2.7 (Linux, 32-разрядная версия):
decimal 36
dict 136
float 16
int 12
list 32
object 8
set 112
str 22
tuple 24
unicode 32
Python 3.3 (Linux, 32-разрядная версия)
decimal 52
dict 144
float 16
int 14
list 32
object 8
set 112
str 26
tuple 24
unicode 26
2016-08-01
OSX, Python 2.7.10 (по умолчанию, 23 октября 2015 г., 19:19:21) [GCC 4.2.1 Совместимый Apple LLVM 7.0.0 (clang-700.0.59.5)] на darwin
decimal 80
dict 280
float 24
int 24
list 72
object 16
set 232
str 38
tuple 56
unicode 52
Все эти ответы собирают информацию мелкого размера. Я подозреваю, что посетители этого вопроса в конечном итоге придут сюда, чтобы ответить на вопрос: "Насколько велик этот сложный объект в памяти?"
Здесь отличный ответ: https://goshippo.com/blog/measure-real-size-any-python-object/
Изюминка:
import sys
def get_size(obj, seen=None):
"""Recursively finds size of objects"""
size = sys.getsizeof(obj)
if seen is None:
seen = set()
obj_id = id(obj)
if obj_id in seen:
return 0
# Important mark as seen *before* entering recursion to gracefully handle
# self-referential objects
seen.add(obj_id)
if isinstance(obj, dict):
size += sum([get_size(v, seen) for v in obj.values()])
size += sum([get_size(k, seen) for k in obj.keys()])
elif hasattr(obj, '__dict__'):
size += get_size(obj.__dict__, seen)
elif hasattr(obj, '__iter__') and not isinstance(obj, (str, bytes, bytearray)):
size += sum([get_size(i, seen) for i in obj])
return size
Используется так:
In [1]: get_size(1)
Out[1]: 24
In [2]: get_size([1])
Out[2]: 104
In [3]: get_size([[1]])
Out[3]: 184
Если вы хотите глубже познакомиться с моделью памяти Python, здесь есть отличная статья, в которой приведен похожий фрагмент кода "общего размера" как часть более подробного объяснения: https://code.tutsplus.com/tutorials/understand-how-much-memory-your-python-objects-use--cms-25609
Я с удовольствием использую Pympler для таких задач. Он совместим со многими версиями Python - asizeof
модуль в частности восходит к 2.2!
Например, используя пример hughdbrown, но с from pympler import asizeof
в начале и print asizeof.asizeof(v)
в конце я вижу (система Python 2.5 на MacOSX 10.5):
$ python pymp.py
set 120
unicode 32
tuple 32
int 16
decimal 152
float 16
list 40
object 0
dict 144
str 32
Ясно, что здесь есть некоторое приближение, но я нашел его очень полезным для анализа и настройки.
Попробуйте профилировщик памяти. профилировщик памяти
Line # Mem usage Increment Line Contents
==============================================
3 @profile
4 5.97 MB 0.00 MB def my_func():
5 13.61 MB 7.64 MB a = [1] * (10 ** 6)
6 166.20 MB 152.59 MB b = [2] * (2 * 10 ** 7)
7 13.61 MB -152.59 MB del b
8 13.61 MB 0.00 MB return a
Также вы можете использовать модуль гуппи.
>>> from guppy import hpy; hp=hpy()
>>> hp.heap()
Partition of a set of 25853 objects. Total size = 3320992 bytes.
Index Count % Size % Cumulative % Kind (class / dict of class)
0 11731 45 929072 28 929072 28 str
1 5832 23 469760 14 1398832 42 tuple
2 324 1 277728 8 1676560 50 dict (no owner)
3 70 0 216976 7 1893536 57 dict of module
4 199 1 210856 6 2104392 63 dict of type
5 1627 6 208256 6 2312648 70 types.CodeType
6 1592 6 191040 6 2503688 75 function
7 199 1 177008 5 2680696 81 type
8 124 0 135328 4 2816024 85 dict of class
9 1045 4 83600 3 2899624 87 __builtin__.wrapper_descriptor
<90 more rows. Type e.g. '_.more' to view.>
А также:
>>> hp.iso(1, [1], "1", (1,), {1:1}, None)
Partition of a set of 6 objects. Total size = 560 bytes.
Index Count % Size % Cumulative % Kind (class / dict of class)
0 1 17 280 50 280 50 dict (no owner)
1 1 17 136 24 416 74 list
2 1 17 64 11 480 86 tuple
3 1 17 40 7 520 93 str
4 1 17 24 4 544 97 int
5 1 17 16 3 560 100 types.NoneType
Когда вы используете встроенную функцию dir([объект]), вы можете использовать встроенную функцию sizeof.
>>> a = -1
>>> a.__sizeof__()
24
Также можно использовать tracemalloc
модуль из стандартной библиотеки Python. Кажется, он хорошо работает для объектов, класс которых реализован на C (например, в отличие от Pympler).