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

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

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

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

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

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

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

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

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

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

Как получить размер памяти / использование объекта 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) 

Обращение к «кортежу» части вопроса

Объявление 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

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

 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).

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

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

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

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