Я использую собственную установку Discourse (2026.5.0-latest). Сегодня я попытался включить YJIT. Я добавил "templates/enable-ruby-yjit.yml" в containers/app.yml и пересобрал приложение.
После завершения пересборки произошло кое-что интересное. Внутри Docker-контейнера я выполнил env | grep RUBY_YJIT_ENABLE и получил RUBY_YJIT_ENABLE=1. Пока всё хорошо. Но затем я выполнил sudo -u discourse RAILS_ENV=production bundle exec rails runner 'puts "YJIT enabled: #{RubyVM::YJIT.enabled?}"; puts RUBY_DESCRIPTION'… и получил:
Таким образом, YJIT не был включён, несмотря на добавление шаблона enable-ruby-yjit.yml. Затем, когда я выполнил sudo -u discourse RAILS_ENV=production bundle exec rails runner 'puts "GlobalSetting.yjit_enabled=#{GlobalSetting.yjit_enabled}"', я получил GlobalSetting.yjit_enabled= — значение nil!
В любом случае, после некоторых манипуляций мне всё же удалось включить YJIT, добавив следующее в containers/app.yml:
env:
DISCOURSE_YJIT_ENABLED: true
Уверен, где-то есть ошибка (GlobalSetting.yjit_enabledникогда не должен возвращать nil), но установка переменной окружения сработала, и надеюсь, кто-то, ищущий это в Google, найдёт эту тему.
Разве это не ошибочная диагностика? Вы проверяете переменные окружения только что созданного процесса Ruby, а не того, который фактически запускает веб-сервер.
Если вы проверите /proc/<pid>/environ процесса Pitchfork, то увидите там переменную окружения YJIT.
Наличие переменной окружения не говорит вам ничего о том, запущен ли Ruby в данный момент с включённым YJIT. В данном конкретном случае переменная окружения установлена, но что-то другое перезаписывало переменную, которую Rails использует для включения (или отключения) YJIT при запуске. Другого объяснения тому, почему GlobalSetting.yjit_enabled= возвращает nil, даже на новом экземпляре Rails, нет. Также нет никаких причин, по которым YJIT должен быть отключён на новом экземпляре Rails.
После добавления переменной окружения DISCOURSE_YJIT_ENABLED в мой файл containers/app.yml:
Это неверно. На уровне Ruby переменная окружения является одним из официальных переключателей. См. официальную документацию Ruby по этой теме здесь:
Это неверно, так как DISCOURSE_YJIT_ENABLED лишь передаёт значение в GlobalSetting.yjit_enabled → config.yjit в файле config/application.rb. Rails использует это для включения YJIT, если он ещё не включён. Он не отключает уже активный YJIT. Таким образом, когда переменная окружения установлена, DISCOURSE_YJIT_ENABLED ничего не делает.
Чтобы дополнительно подтвердить свою точку зрения, я написал плагин, который возвращает информацию о том, включён ли YJIT в моём веб-процессе:
Хм! То есть вы говорите, что мы можем надежно использовать переменную окружения для определения, включен ли YJIT! Я об этом не знал; спасибо за ссылку на документацию Ruby.
Однако я немного запутался. Как это возможно, что env | grep RUBY_YJIT_ENABLE возвращает RUBY_YJIT_ENABLE=1, но новый экземпляр Rails в том же контейнере, когда его просят вывести #{RubyVM::YJIT.enabled?}, выводит false? Разве он не должен выводить true, поскольку, как вы упомянули, эта переменная окружения работает на уровне Ruby?
Вы, наверное, очень заняты, и это не должно иметь значения, так что отвечать не обязательно. Я должен суметь разобраться с этим на своем собственном сервере. Не могли бы вы поделиться своим плагином? Мне нужен способ быть уверенным, что мой сервер Discourse работает на Ruby с включенным YJIT.
Я отмечу ваш ответ как решение, как только воспроизведу ситуацию.