Ractor — механизм изоляции и параллельного выполнения Ruby-кода. В MRI Ruby 3.4 GVL действует внутри каждого Ractor, поэтому разные Ractor могут выполнять Ruby-код параллельно. Объекты могут быть shareable, копироваться или перемещаться при передаче; после move отправитель теряет доступ к перемещённому объекту. Это не разрешение свободно разделять изменяемое состояние. API примера ограничен Ruby 3.4.
Что такое Ractor в Ruby?
Ractor предоставляет изолированные контексты выполнения и обмен сообщениями для параллельной работы. Пример и описание API относятся к Ruby 3.4.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Ractor — механизм для параллельного выполнения с изоляцией состояния, появившийся в Ruby 3.0. Ниже рассматривается именно MRI Ruby 3.4: пример не следует автоматически переносить на другую версию, поскольку API развивается.
У каждого Ractor могут быть собственные потоки. GVL ограничивает одновременное выполнение Ruby-кода потоками внутри одного Ractor, но разные Ractor могут выполнять Ruby-код параллельно на разных ядрах. Это отличает модель от обычного набора потоков внутри одного Ractor. Модель Ractor в Ruby 3.4
# Ruby 3.4
worker = Ractor.new do
value = Ractor.receive
value * 2
end
worker.send(5)
puts worker.take # 10
send помещает сообщение во входящую очередь, Ractor.receive получает его, при необходимости ожидая. В этом примере take получает итоговое значение блока после завершения вычисления. Это демонстрация обмена сообщениями, а не замер производительности. API Ractor 3.4
Передавать можно не только неизменяемые значения. Есть три важных режима:
- Shareable: объект допустимо использовать из нескольких Ractor. Это, например, числа и некоторые замороженные структуры; классы и модули тоже имеют специальный статус совместного использования.
- Copy: непригодные для совместного использования части передаваемой структуры по умолчанию глубоко копируются, если тип допускает копирование.
- Move:
send(object, move: true)передаёт владение; прежние ссылки отправителя на перемещённый объект больше нельзя использовать.
Поверхностный freeze массива не делает автоматически shareable его изменяемые элементы. Для проверки есть Ractor.shareable?, а Ractor.make_shareable пытается подготовить объект к совместному использованию и может завершиться ошибкой.
Изоляция ограничивает доступ к общему состоянию, но не решает конфликты во внешней БД или файлах. Нужно также проверять совместимость библиотек и расширений. Передача больших объектов, создание Ractor и координация имеют стоимость: выигрыш для конкретной CPU-нагрузки подтверждают измерениями, а не самим наличием параллелизма.