Например, сколько памяти требуется для хранения списка из миллиона (32-битных) целых чисел?
alist = range(1000000) # or list(range(1000000)) in Python 3.0
@tmthydvnprt: ваш ответ основан исключительно на одном неверном вызове sys.getsizeof(). Сравните результаты с asizeof.asizeof() из моего ответа (например, в моей системе: sys.getsizeof(range(10**6)) -> 8000072, а asizeof.asizeof(range(10**6)) -> 32000072).
почему один sys.getsizeof() неверен?






"По-разному." Python выделяет место для списков таким образом, чтобы достичь амортизированное постоянное время для добавления элементов в список.
На практике это означает, что с текущей реализацией ... в списке всегда есть пространство, выделенное для числа элементов, равного степени двойки. Таким образом, range (1000000) фактически выделит список, достаточно большой, чтобы содержать 2 ^ 20 элементов (~ 1,045 миллиона).
Это только пространство, необходимое для хранения самой структуры списка (которая представляет собой массив указателей на объекты Python для каждого элемента). 32-разрядная система потребует 4 байта на элемент, 64-разрядная система будет использовать 8 байтов на элемент.
Кроме того, вам нужно место для хранения фактических элементов. Это сильно различается. Для небольших целых чисел (в настоящее время от -5 до 256) дополнительное пространство не требуется, но для больших чисел Python выделяет новый объект для каждого целого числа, которое занимает 10–100 байт и имеет тенденцию фрагментировать память.
Итог: списки все сложно и Python - это нет, хороший способ хранить большие однородные структуры данных. Для этого используйте модуль array или, если вам нужно выполнить векторизованную математику, используйте NumPy.
PS- Кортежи, в отличие от списков, являются не разработан, чтобы к ним постепенно добавлялись элементы. Я не знаю, как работает распределитель, но даже не думаю об использовании его для больших структур данных :-)
Кортежи не просто предназначены для добавления, они могут быть добавлены к не могу. Ближайший аналог предполагает создание нового кортежа полностью (а затем, возможно, уничтожение старого), что очень неэффективно.
Да, в самом деле. Я предполагаю, что я получил ... Python не только не позволяет добавлять кортежи, но и внутренняя память для них не управляется таким образом, чтобы сделать это эффективным.
Нитпик: Это не фактор роста, основанный на силе двух. Он перераспределяет на размер / 8 плюс 6 (или 3, если <= 8 элементов). Он пропорционален размеру, поэтому все равно будет добавляться амортизированная константа, но используется только ~ 12,5% дополнительного пространства. См. Реализацию на listobject.c.
Я уверен, что это зависит от конкретной реализации. Конечно, это зависит от внутреннего представления целых чисел - вы не можете предполагать, что они будут храниться как 32-битные, поскольку Python дает вам произвольно большие целые числа, поэтому, возможно, небольшие целые числа хранятся более компактно.
На моем Python (2.5.1 в Fedora 9 на ядре 2 duo) размер VmSize до выделения составляет 6896 КБ, после - 22684 КБ. После назначения еще одного миллиона элементов VmSize становится 38340 КБ. Это очень грубо означает около 16000 КБ для 1000000 целых чисел, что составляет около 16 байт на целое число. Это предполагает много накладных расходов для списка. Я бы отнесся к этим числам с большой долей скепсиса.
Полезные ссылки:
Как получить размер памяти / использование объекта 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)
Могу ли я использовать sys.getsizeof () для получения размера списка?
@Alcott: Модуль asizeof использует sys.getsizeof, если он доступен и применим.
@Alcott: это модуль Pympler. from pympler import asizeof и asizeof.asizeof(object)
Обращение к "кортежной" части вопроса
Объявление 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 для целых чисел).
Добавлено примечание «мелкий vs полноразмерный».
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, когда он доступен и применим. Смотрите мой ответ.
Попробуй это? Графический пример, который я сделал: stackoverflow.com/a/30008338/2087463