Почему питон кушает много памяти

Короткая заметка о том, почему 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 еще и притормаживает.

Такие вот пироги с котятами.

blog comments powered by Disqus