Почему питон кушает много памяти
Короткая заметка о том, почему python любит память. Я, возможно, покажусь Капитаном Очевидностью, но все же.
Вот возьмем такой рафинированый пример:
class A(object):
def __init__(self, i):
self.j = i
x = [A(i) for i in xrange(1000000)]
input()
Запустим его на 32 битной системе (с 32 битным питоном) и увидим что он кушает, примерно, 190 МБ памяти.
Как-то много для массива из миллиона указателей на объекты размером в 4 байта.
Теперь берем 64 битную систему и проверяем сколько скушает данный пример. У piranha получилось 384 МБ - в примерно два раза больше чем у меня.
Упс.
А теперь попытаемся разобраться чем же это все может быть вызвано.
Мне было совсем лениво заниматься тестами памяти, тем более что кто-то это уже сделал - http://www.valuedlessons.com/2008/10/blog-post.html
Посмотрим на табличку. new-style class = 336, int = 24. (336+24)*1000000 = 360,000,000 или ~351 МБ. Из количества используемой памяти можно сделать вывод, что тесты проводились на 64-битной системе. Остальное можно списать на стандартные либы, системные либы в процессе питона и так далее.
Откуда столько памяти на один int? Вспоминаем что питон работает с объектами. Имена переменных это просто ссылки на объекты. Кроме того, сборщик мусора работает на подсчете ссылок, так что каждый объект должен хранить количество ссылок на себя.
Вот и получается - поскольку все на указателях, то при переходе на архитектуру с вдвое большим размером оных, использование памяти в питоне увеличивается почти в два раза. Да и без перехода получается ерунда - 24 байта на значение в 4 байта это тоже overkill.
Так что, если у вас памяти не очень много (VPS, etc) - однозначно использовать 32 битный питон. Если памяти много (больше 3 ГБ), то тогда прийдется использовать 64 битный, так как PAE еще и притормаживает.
Такие вот пироги с котятами.