Ruby использует сложную систему управления памятью, сочетающую автоматическое управление через сборщик мусора (GC) с ручной оптимизацией. Рассмотрим ключевые аспекты этой системы.
Ruby применяет маркировку и очистку (mark-and-sweep) для управления памятью:
# Пример работы GC
obj = Object.new
obj = nil # Теперь оригинальный объект может быть собран GC
С Ruby 2.1 используется улучшенный алгоритм:
GC.stat # Показывает статистику по GC
# => {:count=>25, :heap_allocated_pages=>100, ...}
GC.start # Принудительный запуск сборщика мусора
# Символы и небольшие целые числа не собираются GC
:symbol.object_id == :symbol.object_id # => true
100.object_id == 100.object_id # => true
# Объекты > 40 байт размещаются вне кучи
large_string = "a" * 1000
require 'objspace'
ObjectSpace.count_objects # => {:TOTAL=>55254, :FREE=>1021, ...}
ObjectSpace.memsize_of("hello") # => 40
# Запуск с профилированием памяти
ruby -robjspace -e 'p ObjectSpace.count_objects'
Избегайте утечек памяти:
# Плохо:
$global_array ||= []
$global_array << "data" # Бесконечный рост
Используйте замороженные строки:
# Хорошо:
FROZEN_STR = "constant".freeze
Переиспользуйте объекты:
# Вместо создания новых массивов в цикле
buffer = []
loop do
buffer.clear
# Используем buffer
end
class Node
attr_accessor :next
end
a = Node.new
b = Node.new
a.next = b
b.next = a # Циклическая ссылка
# Опасный кэш без ограничения
CACHE = {}
def cached(key)
CACHE[key] ||= expensive_operation(key)
end
# В Ruby 2.7+
GC.auto_compact = true # Включает автоматическую компактификацию
GC.interval_ratio = 20 # Настройка интервалов GC
RUBY_GC_HEAP_INIT_SLOTS=100000
RUBY_GC_MALLOC_LIMIT=16000000
Ключевые аспекты управления памятью в Ruby:
ObjectSpace
Для эффективной работы:
Понимание этих механизмов помогает писать более эффективные и стабильные Ruby-приложения.