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

StackOverflow https://stackoverflow.com/questions/135664

  •  02-07-2019
  •  | 
  •  

Вопрос

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

alist = range(1000000) # or list(range(1000000)) in Python 3.0
Это было полезно?

Решение 2

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

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

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

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

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

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

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

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

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

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

Объявление 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, объект.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 предоставляет вам сколь угодно большие целые числа, поэтому, возможно, маленькие целые числа хранятся более компактно.

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top