Как работает garbage collector в Python и какие механизмы он использует?
Что проверяют
Различаете ли вы два механизма: подсчёт ссылок как основной путь освобождения памяти и отдельный сборщик циклов как дополнение. И понимаете ли, что это устройство CPython, а не требование языка.
Как отвечать
- Подсчёт ссылок: у каждого объекта счётчик, он растёт с новой ссылкой и падает с исчезнувшей. На нуле память освобождается немедленно и детерминированно. Поэтому в CPython файл закрывается сразу после выхода из области видимости, а в PyPy нет.
- Циклы счётчик разорвать не может: два объекта, ссылающиеся друг на друга, держат счётчики выше нуля. Их собирает
gc, обходя контейнеры и вычитая внутренние ссылки, чтобы найти группы, недостижимые снаружи. - Запускается он не по объёму памяти, а по разнице между числом созданных и удалённых контейнеров. Пороги по умолчанию 700, 10 и 10 (
gc.get_threshold()). - Поколения: молодые объекты проверяются часто, пережившие сборку переезжают в старшие. В CPython 3.13 сборка циклов стала инкрементальной, длинные паузы на больших кучах сократились.
- Объекты с
__del__внутри цикла собираются начиная с Python 3.4 (PEP 442), старое правило про их вечную утечку неверно. - На практике:
gc.freeze()перед fork экономит память при копировании при записи, утечки ищут черезgc.get_objects(), tracemalloc и objgraph.
import gc
class Node:
peer = None
a, b = Node(), Node()
a.peer, b.peer = b, a
del a, b # счётчики не нули, объекты живы
print(gc.collect()) # сколько объектов собраноГде спотыкаются
Говорят, что сборщик запускается при достижении порога памяти. Порог считается в количестве аллокаций контейнеров, объём памяти в решении не участвует.
Считают, что память освобождает сборщик. Подавляющее большинство объектов убирает подсчёт ссылок, а gc трогает только контейнеры, способные образовать цикл.
Приравнивают del x к освобождению памяти. Это удаление имени и минус единица к счётчику, не более.
Переносят механику на язык целиком. В свободнопоточной сборке 3.13 и новее подсчёт ссылок устроен иначе, а сборка циклов останавливает потоки.