GC автоматически освобождает память недостижимых объектов. В стандартном сборщике CRuby используются mark-and-sweep, поколения и инкрементальная маркировка. Присваивание nil убирает одну ссылку, но не гарантирует немедленной сборки, отсутствия других ссылок или уменьшения RSS процесса.
Как работает сборщик мусора в Ruby?
Достижимость объектов, mark-and-sweep, поколения и инкрементальная маркировка в CRuby. Почему nil не означает немедленное освобождение памяти.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Сборщик мусора, или GC, управляет памятью объектов автоматически. Он ищет объекты, недостижимые из живых корней программы, и освобождает занимаемое ими место. Важно именно отсутствие достижимого пути, а не субъективное «объект больше не нужен».
Для стандартного GC в CRuby характерны:
- Mark-and-sweep: маркировка достижимых объектов и освобождение непомеченных.
- Поколения: молодые объекты проверяются при minor collection; major collection затрагивает также старые.
- Инкрементальная маркировка: часть работы распределяется между шагами исполнения программы. Это уменьшает отдельные паузы, но не устраняет расходы GC полностью.
value = Object.new
other = value
value = nil
# Объект всё ещё достижим через other.
other = nil
# Теперь эти переменные его не удерживают.
Присваивание nil не запускает обязательную немедленную сборку. Другие ссылки могут оставаться в коллекциях, замыканиях или долгоживущих объектах. Освобождённое место в куче может использоваться повторно внутри процесса, не уменьшая сразу его RSS.
В CRuby наблюдать за сборщиком помогают GC.stat, GC.count и GC::Profiler. Не следует начинать оптимизацию с отключения GC или принудительного GC.start после каждого запроса: сначала измеряют удерживаемые объекты, частоту сборок и паузы.
Это описание стандартного сборщика CRuby, а не обещание одинакового устройства всех реализаций Ruby. Параметры и статистика зависят от версии и реализации. Интерфейс GC в Ruby 3.4