Сколько байтов на элемент содержится в списке Python (кортеж)? - PullRequest
13 голосов
/ 26 сентября 2008

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

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

Ответы [ 6 ]

23 голосов
/ 26 сентября 2008

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

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

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

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

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

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

14 голосов
/ 26 сентября 2008

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

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

Обращаясь к "кортежу" части вопроса

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

3 голосов
/ 02 октября 2008

Новая функция, 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).

2 голосов
/ 26 сентября 2008

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

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

0 голосов
/ 02 октября 2008

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

Если дело обстоит именно так, вместо того, чтобы пытаться выяснить, сколько ОЗУ занимает каждый виджет, выясните, сколько ОЗУ, скажем, 10000 виджетов занимает, и умножьте, чтобы получить реальный размер.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...