Получи случайную криптовалюту за регистрацию!

Расскажите о сборщике мусора в Python Как правило, вам не нуж | Python вопросы с собеседований

Расскажите о сборщике мусора в Python

Как правило, вам не нужно беспокоиться о сборщике мусора и работе с памятью когда вы пишете код на Python. Как только объекты больше не нужны, Python автоматически освобождает память из под них. Несмотря на это, понимание как работает GC поможет писать более качественный код.

Менеджер памяти

В отличие от других популярных языков, Python не освобождает всю память обратно операционной системе как только он удаляет какой либо объект. Вместо этого, он использует дополнительный менеджер памяти, предназначенный для маленьких объектов (размер которых меньше чем 512 байт). Для работы с такими объектами он выделяет большие блоки памяти, в которых в дальнейшем будет хранится множество маленьких объектов.

Как только один из маленьких объект удаляется — память из под него не переходит операционной системе, Python оставляет её для новых объектов с таким же размером. Если в одном из выделенных блоков памяти не осталось объектов, то Python может высвободить его операционной системе. Как правило, высвобождение блоков случается когда скрипт создает множество временных объектов.

Таким образом, если долгоживущий Python процесс с течением времени начинает потреблять больше памяти, то это совсем не означает, что в вашем коде есть проблема с утечкой памяти. Если вы хотите узнать больше о менеджере памяти в Python, вы можете прочитать об этом в другой моей статье (англ.).

Алгоритмы сборки мусора

Стандартный интерпретатор питона (CPython) использует сразу два алгоритма, подсчет ссылок и generational garbage collector (далее GC), более известный как стандартный модуль gc из Python.

Алгоритм подсчета ссылок очень простой и эффективный, но у него есть один большой недостаток. Он не умеет определять циклические ссылки. Именно из-за этого, в питоне существует дополнительный сборщик, именуемый поколенческий GC, который следит за объектами с потенциальными циклическими ссылками.

В Python, алгоритм подсчета ссылок является фундаментальным и не может отключен, тогда как GC опционален и может быть отключен.

Алгоритм подсчета ссылок

Алгоритм подсчета ссылок это одна из самых простых техник для сборки мусора. Объекты удаляются как только на них больше нет ссылок.

В Python, переменные не хранят значения, а выступают в роли ссылок на объекты. То есть когда вы присваивайте значение новой переменной, то сначала создается объект с этим значением, а уже потом переменная начинает ссылаться на него. На один объект может ссылаться множество переменных.

Каждый объект в Python содержит дополнительное поле (счетчик ссылок), в котором хранится количество ссылок на него. Как только кто-то ссылается на объект, это поле увеличивается на единицу. Если по какой-то причине ссылка пропадает, то это поле уменьшается на один.

Примеры, когда количество ссылок увеличивается:
- оператор присваивания
- передача аргументов
- вставка нового объекта в лист (увеличивается количество ссылок для объекта)
конструция вида foo = bar (foo начинается ссылаться на тот же объект, что и bar)

Как только счетчик ссылок для определенного объекта достигает нуля интерпретатор запускает процесс уничтожения объекта. Если удаленный объект содержал ссылки на другие объекты, то эти ссылки также удаляются. Таким образом, удаление одного объекта может повлечь за собой удаление других.

Например, если удаляется список, то счетчик ссылок во всех его элементах уменьшается на один. Если все объекты внутри списка больше нигде не используются, то они также будут удалены.

Переменные, которые объявлены вне функций, классов и блоков называются глобальными. Как правило, жизненный цикл таких переменных равен жизни Python процесса. Таким образом, количество ссылок на объекты на которые ссылаются глобальные переменные никогда не падает до нуля.

Переменные, которые объявлены внутри блока имеют локальную видимость (они видны только внутри блока). Как только интерпретатор питона выходит из блока он уничтожает все ссылки созданные локальными переменными внутри него.

Вы всегда можете проверить количество ссылок используя функцию sys.getrefcount.

@python_job_interview