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

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

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

Ответ 1

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

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

Размеры памяти для объектов python?

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

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

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

  • Используйте сторонний модуль расширения, который определяет некоторый тип 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)

Ответ 2

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

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

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

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

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

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

Ответ 3

Адресация части "кортежа" вопроса

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

struct PyTuple {
  size_t refcount; // tuple 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

Ответ 4

Новая функция getsizeof() принимает Python и возвращает сумму памяти, используемой объектом, измеренной в байтах. Возврат встроенных объектов правильные результаты; третье лицо расширения не могут, но могут определять __sizeof__(), чтобы вернуть размер объектов.

[email protected]:~/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).

Ответ 5

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

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

Ответ 6

Я опасаюсь, почему вы спрашиваете. Вы пытаетесь выяснить, сколько памяти вам понадобится для данной реализации? Скажем, вы собираетесь прочитать 10 000 000 виджетов и хотите узнать, сколько оперативной памяти он будет сосать?

Если это так, вместо того, чтобы пытаться выяснить, сколько памяти занимает каждый виджет, выясните, сколько оперативной памяти, скажем, 10 000 виджетов принимает и умножается, чтобы получить реальный размер.