Размер в памяти структуры Python

Есть ли ссылка на размер памяти структуры данных Python на 32- и 64-битных платформах?

Если нет, было бы неплохо иметь его на SO. Чем полнее, тем лучше! Итак, сколько байтов используется следующими структурами Python (в зависимости от len и типа содержимого, когда это необходимо)?

  • int
  • float
  • ссылка
  • str
  • строка Юникода
  • tuple
  • list
  • dict
  • set
  • array.array
  • numpy.array
  • deque
  • объект классов нового стиля
  • объект классов в старом стиле
  • ... и все, что я забываю!

(Для контейнеров, которые хранят только ссылки на другие объекты, мы, очевидно, не хотим подсчитывать размер самого элемента, поскольку он может быть общим.)

Кроме того, есть ли способ получить память, используемую объектом во время выполнения (рекурсивно или нет)?


person LeMiz    schedule 25.08.2009    source источник
comment
Здесь можно найти множество полезных объяснений stackoverflow.com/questions/1059674/python-memory-model . Хотелось бы увидеть более систематический обзор, хотя   -  person LeMiz    schedule 26.08.2009
comment
Для массива NumPy a используйте a.nbytes.   -  person Will    schedule 02.05.2014
comment
Если вас интересует графическое представление этого, я однажды нарисовал его график: stackoverflow.com/a/30008338/2087463   -  person tmthydvnprt    schedule 13.03.2016


Ответы (7)


Рекомендация из предыдущего вопроса для этого было использовать 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) [Apple LLVM 7.0.0, совместимый с GCC 4.2.1 (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
person hughdbrown    schedule 25.08.2009
comment
Спасибо и извините за обман за второй вопрос ... очень плохо, я использую 2.5, а не 2.6 ... - person LeMiz; 26.08.2009
comment
Я забыл, что у меня есть виртуальный ящик с последней версией Ubuntu! Странно, sys.getsizeof (dict) для меня 136 (python 2.6 работает на kubuntu vm, размещенном на OS X, поэтому я ни в чем не уверен) - person LeMiz; 26.08.2009
comment
@LeMiz: Для меня (Python 2.6, Windows XP SP3) sys.getsizeof (dict) - ›436; sys.getsizeof (dict ()) - ›140 - person John Machin; 26.08.2009
comment
LeMiz-Kubuntu: python2.6 Python 2.6.2 (release26-maint, 19 апреля 2009 г., 01:56:41) [GCC 4.3.3] в linux2 Для получения дополнительной информации введите help, авторские права, кредиты или лицензия. ››› import sys ››› sys.getsizeof (dict) 436 ››› sys.getsizeof (dict ()) 136 - person LeMiz; 26.08.2009
comment
Разве значения не должны быть 0, 0.0, '' и u'' для согласованности? - person SilentGhost; 26.08.2009
comment
К сожалению, это не работает для массивов NumPy (они возвращают 44 байта независимо от их размера, с версией 1.5). - person Eric O Lebigot; 05.02.2010
comment
как насчет создания кортежа констант и использования type (): для элемента в кортеже (0, 0.0, u '' и т. д.): print type (item), sys.getsizeof (item) - person rbp; 20.03.2014
comment
десятичный? Что это? - person Zizouz212; 07.06.2015
comment
Я полагаю, размер указан в байтах, но почему он нигде не записан, даже в pythonhosted.org/Pympler - person Zhomart; 21.01.2016
comment
@Zhomart: Мне это кажется довольно ясным. sys.getsizeof (object [, default]) Возвращает размер объекта в байтах. Объект может быть любым типом объекта. Все встроенные объекты будут возвращать правильные результаты, но это не обязательно должно выполняться для сторонних расширений, поскольку это зависит от реализации. docs.python.org/3/library/sys.html - person hughdbrown; 22.01.2016
comment
Да, я написал комментарий к другому ответу. Я хотел пожаловаться на Пимплера. Спасибо, что указали на @hughdbrown. - person Zhomart; 26.01.2016

Все эти ответы собирают информацию о мелких размерах. Я подозреваю, что посетители этого вопроса в конечном итоге будут здесь пытаться ответить на вопрос: «Насколько велик этот сложный объект в памяти?»

Здесь есть отличный ответ: 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/понять-сколько-памяти-использование-ваших-объектов-python-cms-25609

person Kobold    schedule 30.11.2016
comment
Таким образом, это должно дать общий объем памяти, используемый, например, dict, содержащим несколько массивов и / или других dicts? - person Charly Empereur-mot; 08.10.2019
comment
@ CharlyEmpereur-mot, ага. - person Kobold; 10.10.2019
comment
Отличный ответ. Однако, похоже, это не работает для скомпилированных объектов cython. В моем случае этот метод возвращает 96 для указателя на объект cython в памяти. - person ferdynator; 27.11.2019

Я с радостью использую 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

Ясно, что здесь есть некоторое приближение, но я нашел его очень полезным для анализа и настройки посадочного места.

person Alex Martelli    schedule 26.08.2009
comment
Некоторые любопытства: у большинства из вас числа на 4 выше; объект 0; а десятичная дробь примерно в 4 раза больше, по вашей оценке. - person hughdbrown; 26.08.2009
comment
Ага. Число 4 выше на самом деле в основном выглядит как округление до кратного 8, что, по моему мнению, является правильным с точки зрения поведения malloc. Понятия не имею, почему десятичное число так искажается (с pympler на 2.6 тоже). - person Alex Martelli; 26.08.2009
comment
Фактически, вы должны использовать pympler.asizeof.flatsize (), чтобы получить функциональность, аналогичную sys.getsizeof (). Существует также параметр align =, который вы можете использовать (который по умолчанию равен 8, как указал Алекс). - person Pankrat; 11.09.2009
comment
@AlexMartelli Привет, Алекс! .. Почему минимальный размер символа в Python составляет 25 байт. >>> getsizeof('a') дает 25, а >>> getsizeof('ab') дает 26 ` - person Grijesh Chauhan; 17.01.2013
comment
Я полагаю, размер указан в байтах, но почему он нигде не записан, даже в pythonhosted.org/Pympler - person Zhomart; 26.01.2016

Попробуйте профайлер памяти. профилировщик памяти

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
person Tampa    schedule 01.10.2012
comment
Точность составляет 1/100 МБ или 10,24 байта. Это хорошо для макроанализа, но я сомневаюсь, что такая точность приведет к точному сравнению структур данных, как задано в вопросе. - person Zoran Pavlovic; 30.11.2014

Также вы можете использовать модуль guppy.

>>> 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
person Omid Raha    schedule 26.12.2013

Также можно использовать модуль tracemalloc из стандартной библиотеки Python. Кажется, он хорошо работает для объектов, класс которых реализован на C (например, в отличие от Pympler).

person zahypeti    schedule 29.03.2020

Когда вы используете встроенную функцию dir([object]), вы можете получить __sizeof__ встроенной функции.

>>> a = -1
>>> a.__sizeof__()
24
person hello_god    schedule 05.02.2017