Сколько байтов на элемент в списке (кортеже) Python?

Например, сколько памяти требуется для хранения списка из миллиона (32-битных) целых чисел?

alist = range(1000000) # or list(range(1000000)) in Python 3.0

Попробуй это? Графический пример, который я сделал: stackoverflow.com/a/30008338/2087463

tmthydvnprt 13.03.2016 16:51

@tmthydvnprt: ваш ответ основан исключительно на одном неверном вызове sys.getsizeof(). Сравните результаты с asizeof.asizeof() из моего ответа (например, в моей системе: sys.getsizeof(range(10**6)) -> 8000072, а asizeof.asizeof(range(10**6)) -> 32000072).

jfs 13.03.2016 20:31

почему один sys.getsizeof() неверен?

tmthydvnprt 13.03.2016 20:49
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
17
3
13 668
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

"По-разному." Python выделяет место для списков таким образом, чтобы достичь амортизированное постоянное время для добавления элементов в список.

На практике это означает, что с текущей реализацией ... в списке всегда есть пространство, выделенное для числа элементов, равного степени двойки. Таким образом, range (1000000) фактически выделит список, достаточно большой, чтобы содержать 2 ^ 20 элементов (~ 1,045 миллиона).

Это только пространство, необходимое для хранения самой структуры списка (которая представляет собой массив указателей на объекты Python для каждого элемента). 32-разрядная система потребует 4 байта на элемент, 64-разрядная система будет использовать 8 байтов на элемент.

Кроме того, вам нужно место для хранения фактических элементов. Это сильно различается. Для небольших целых чисел (в настоящее время от -5 до 256) дополнительное пространство не требуется, но для больших чисел Python выделяет новый объект для каждого целого числа, которое занимает 10–100 байт и имеет тенденцию фрагментировать память.

Итог: списки все сложно и Python - это нет, хороший способ хранить большие однородные структуры данных. Для этого используйте модуль array или, если вам нужно выполнить векторизованную математику, используйте NumPy.

PS- Кортежи, в отличие от списков, являются не разработан, чтобы к ним постепенно добавлялись элементы. Я не знаю, как работает распределитель, но даже не думаю об использовании его для больших структур данных :-)

Кортежи не просто предназначены для добавления, они могут быть добавлены к не могу. Ближайший аналог предполагает создание нового кортежа полностью (а затем, возможно, уничтожение старого), что очень неэффективно.

Thomas Wouters 26.09.2008 00:15

Да, в самом деле. Я предполагаю, что я получил ... Python не только не позволяет добавлять кортежи, но и внутренняя память для них не управляется таким образом, чтобы сделать это эффективным.

Dan Lenski 26.09.2008 00:18

Нитпик: Это не фактор роста, основанный на силе двух. Он перераспределяет на размер / 8 плюс 6 (или 3, если <= 8 элементов). Он пропорционален размеру, поэтому все равно будет добавляться амортизированная константа, но используется только ~ 12,5% дополнительного пространства. См. Реализацию на listobject.c.

Brian 26.09.2008 02:11

Я уверен, что это зависит от конкретной реализации. Конечно, это зависит от внутреннего представления целых чисел - вы не можете предполагать, что они будут храниться как 32-битные, поскольку Python дает вам произвольно большие целые числа, поэтому, возможно, небольшие целые числа хранятся более компактно.

На моем Python (2.5.1 в Fedora 9 на ядре 2 duo) размер VmSize до выделения составляет 6896 КБ, после - 22684 КБ. После назначения еще одного миллиона элементов VmSize становится 38340 КБ. Это очень грубо означает около 16000 КБ для 1000000 целых чисел, что составляет около 16 байт на целое число. Это предполагает много накладных расходов для списка. Я бы отнесся к этим числам с большой долей скепсиса.

Ответ принят как подходящий

Полезные ссылки:

Как получить размер памяти / использование объекта Python

Объемы памяти объектов Python?

если вы поместите данные в словарь, как мы рассчитаем размер данных?

Однако они не дают однозначного ответа. Путь:

  1. Измерьте память, потребляемую интерпретатором Python, со списком или без него (используйте инструменты ОС).

  2. Используйте сторонний модуль расширения, который определяет какой-то sizeof (PyObject).

Обновлять:

Рецепт 546530: Размер объектов Python (пересмотренный)

import asizeof

N = 1000000
print asizeof.asizeof(range(N)) / N
# -> 20 (python 2.5, WinXP, 32-bit Linux)
# -> 33 (64-bit Linux)

Могу ли я использовать sys.getsizeof () для получения размера списка?

Alcott 12.09.2011 03:50

@Alcott: Модуль asizeof использует sys.getsizeof, если он доступен и применим.

jfs 12.09.2011 13:10

@Alcott: это модуль Pympler. from pympler import asizeof и asizeof.asizeof(object)

serv-inc 10.11.2015 16:57

Обращение к "кортежной" части вопроса

Объявление PyTuple CPython в типичной конфигурации сборки сводится к следующему:

struct PyTuple {
  size_t refcount; // tuple's reference count
  typeobject *type; // tuple type object
  size_t n_items; // number of items in tuple
  PyObject *items[1]; // contains space for n_items elements
};

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

sizeof(size_t) x 2 + sizeof(void*) x (n_items + 1).

Это дает размер кортежа мелкий. Чтобы получить размер полный, вам также необходимо добавить общее количество байтов, потребляемых графом объектов, укорененным в массиве PyTuple::items[].

Стоит отметить, что процедуры построения кортежа гарантируют, что когда-либо будет создан только один экземпляр пустого кортежа (singleton).

Использованная литература: Python.h, object.h, tupleobject.h, tupleobject.c

Это не так просто, например, () 32, (1,) 48, (1, 2) 72, (1, 2, 3) 88 - размеры, включая размеры элементов (16 для целых чисел).

jfs 26.09.2008 19:17

Добавлено примечание «мелкий vs полноразмерный».

Constantin 27.09.2008 00:02

A new function, getsizeof(), takes a Python object and returns the amount of memory used by the object, measured in bytes. Built-in objects return correct results; third-party extensions may not, but can define a __sizeof__() method to return the object’s size.

kveretennicov@nosignal:~/py/r26rc2$ ./python
Python 2.6rc2 (r26rc2:66712, Sep  2 2008, 13:11:55) 
[GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)] on linux2
>>> import sys
>>> sys.getsizeof(range(1000000))
4000032
>>> sys.getsizeof(tuple(range(1000000)))
4000024

Очевидно, что возвращаемые числа не включают память, потребляемую содержащимися объектами (sys.getsizeof (1) == 12).

Модуль asizeof использует sys.getsizeof, когда он доступен и применим. Смотрите мой ответ.

jfs 03.10.2008 05:26

Другие вопросы по теме