Как и когда сборщик мусора (GC) в Python освобождает память

Ответ

Сборщик мусора (GC) в CPython использует два основных механизма для освобождения памяти:

  1. Подсчет ссылок (Reference Counting) Это основной и самый быстрый механизм. У каждого объекта есть счетчик, который отслеживает, сколько переменных на него ссылается. Когда счетчик достигает нуля, память из-под объекта освобождается немедленно.

    import sys
    
    a = [] # Создан объект list, счетчик ссылок = 1
    b = a  # Счетчик ссылок на тот же объект = 2
    
    print(sys.getrefcount(a)) # Выведет 3 (a, b и временная ссылка в getrefcount)
    
    del a
    del b  # Счетчик ссылок стал 0, объект удаляется
  2. Обнаружение циклических ссылок (Generational GC) Подсчет ссылок не работает, если объекты ссылаются друг на друга, образуя цикл. Для таких случаев GC периодически запускает алгоритм, который находит "острова" изолированных объектов (недостижимых из основной программы) и удаляет их.

    Пример циклической ссылки:

    import gc
    
    class Node:
        def __init__(self, name):
            self.name = name
            self.neighbor = None
    
    # Создаем два объекта, которые ссылаются друг на друга
    node1 = Node('A')
    node2 = Node('B')
    node1.neighbor = node2
    node2.neighbor = node1 # Цикл: node1 -> node2 -> node1
    
    # Удаляем внешние ссылки на объекты
    del node1
    del node2
    
    # Объекты все еще в памяти, т.к. их счетчики ссылок не равны 0.
    # Они будут удалены при следующем запуске сборщика мусора.
    gc.collect() # Принудительный запуск для демонстрации

    Таким образом, большинство объектов удаляется мгновенно, а циклические зависимости очищаются периодически.