← Назад к вопросам

Какие механизмы garbage collection знаешь?

2.0 Middle🔥 151 комментариев
#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Механизмы Garbage Collection в Python

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

1. Reference Counting (Подсчёт ссылок)

Основной и самый быстрый механизм в CPython. Каждый объект имеет счётчик ссылок, и когда он становится нулевым, объект немедленно удаляется.

import sys

obj = []
print(sys.getrefcount(obj))  # 2 (сама переменная + параметр getrefcount)

ref1 = obj
print(sys.getrefcount(obj))  # 3 (ещё одна ссылка)

del ref1
print(sys.getrefcount(obj))  # 2 (ссылка удалена)

del obj  # Объект удалён из памяти

2. Garbage Collection для циклических ссылок

Когда объекты ссылаются друг на друга циклически, reference counting не может их удалить автоматически. Для этого используется cyclic garbage collection.

import gc

class Node:
    def __init__(self, name):
        self.name = name
        self.next = None
    
    def __del__(self):
        print(f"Node {self.name} deleted")

# Создание циклической ссылки
node1 = Node("A")
node2 = Node("B")
node1.next = node2
node2.next = node1  # Цикл!

# Без явного сборки мусора объекты не удаляются
del node1, node2

# Явная сборка мусора
print(f"Garbage collected: {gc.collect()} objects")

3. Поколения в Garbage Collection

Python использует поколенческий подход: объекты разделены на 3 поколения. Молодые объекты проверяются чаще, старые — реже.

import gc

# Получить информацию о поколениях
for generation in range(gc.get_count().__len__()):
    count = gc.get_count()[generation]
    threshold = gc.get_threshold()[generation]
    print(f"Generation {generation}: {count} objects, threshold: {threshold}")

# Пороги для запуска GC
print(f"GC thresholds: {gc.get_threshold()}")  # (700, 10, 10)

# Изменить пороги
gc.set_threshold(1000, 15, 15)

# Сборка конкретного поколения
gc.collect(generation=0)  # Собрать только молодое поколение

4. Явная сборка мусора

Можно явно запустить сборку мусора для контроля над производительностью.

import gc
import time

# Отключить автоматическую сборку
gc.disable()

# Выполнить операции
data = [list(range(1000)) for _ in range(10000)]

# Явная сборка в нужный момент
start = time.time()
gc.collect()
end = time.time()

print(f"GC took {end - start:.4f} seconds")

# Включить обратно
gc.enable()

5. Получение объектов, доступных для сборки

import gc

# Проверить, какие объекты становятся недостижимыми
gc.set_debug(gc.DEBUG_LEAK)

class Resource:
    def __del__(self):
        print("Resource cleanup")

resource = Resource()
del resource

gc.collect()

# Получить список объектов со своими ссылками
gc.garbage  # Список объектов, которые не могут быть удалены

6. Слабые ссылки (Weak References)

Слабые ссылки не увеличивают счётчик ссылок, позволяя объекту быть удалённым.

import weakref

class CachedData:
    def __init__(self, value):
        self.value = value
    
    def __del__(self):
        print("CachedData deleted")

data = CachedData(42)
weak_ref = weakref.ref(data)

print(f"Data value: {weak_ref().value}")  # 42

del data
print(f"After deletion: {weak_ref()}")  # None

7. WeakKeyDictionary и WeakValueDictionary

Словари со слабыми ссылками для кэширования:

import weakref

class User:
    def __init__(self, id, name):
        self.id = id
        self.name = name
    
    def __repr__(self):
        return f"User({self.id}, {self.name})"

# Кэш пользователей со слабыми ссылками
user_cache = weakref.WeakValueDictionary()

user1 = User(1, "Alice")
user2 = User(2, "Bob")

user_cache[1] = user1
user_cache[2] = user2

print(len(user_cache))  # 2

del user1
print(len(user_cache))  # 1 — user1 был удалён

8. Context Managers для управления ресурсами

Использование with для автоматического освобождения ресурсов:

class DatabaseConnection:
    def __init__(self, name):
        self.name = name
    
    def __enter__(self):
        print(f"Opening connection: {self.name}")
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        print(f"Closing connection: {self.name}")
    
    def execute(self, query):
        print(f"Executing: {query}")

with DatabaseConnection("DB1") as db:
    db.execute("SELECT * FROM users")

print("Connection closed")

9. Отслеживание утечек памяти

import gc
import objgraph

# Получить объекты определённого типа
lists = gc.get_objects()
lists_count = sum(1 for obj in lists if isinstance(obj, list))
print(f"Number of lists: {lists_count}")

# Сравнить состояние памяти
objgraph.show_growth()  # Показать объекты, которые выросли

# Найти циклические ссылки
gc.set_debug(gc.DEBUG_SAVEALL)
gc.collect()
for obj in gc.garbage:
    print(obj)

10. Оптимизация GC

import gc

# Для операций, критичных к времени
gc.disable()

try:
    # Критичная операция
    result = process_large_dataset()
finally:
    gc.enable()
    gc.collect()  # Сборка мусора после завершения

# Для фоновых операций
gc.set_threshold(10000, 15, 15)  # Реже запускать GC

Механизмы в кратце

МеханизмОписаниеКогда используется
Reference CountingПодсчёт ссылокОсновной механизм CPython
Cyclic GCСборка циклических ссылокАвтоматически каждое поколение
Weak ReferencesСсылки без увеличения счётчикаКэширование и предотвращение утечек
Context ManagersЯвное управление ресурсамиФайлы, соединения, блокировки

Best Practices

  • Используй with для управления ресурсами (файлы, соединения)
  • Избегай циклических ссылок или удаляй их явно
  • Отключай GC только при необходимости оптимизации
  • Используй weak references для кэшей и обратных ссылок
  • Профилируй память перед оптимизацией
  • Не полагайся на del() — используй контекстные менеджеры

Понимание GC критично для написания эффективного и надёжного Python кода.

Какие механизмы garbage collection знаешь? | PrepBro