Включение YJIT через шаблон не работает

Привет,

Я использую собственную установку 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 enabled: false

ruby 3.4.7 (2025-10-08 revision 7a5688e2a2) +PRISM [x86_64-linux] 

Таким образом, 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.

root@raspberrypi5:/var/discourse# cat /proc/3331660/environ | tr '\0' '\n' | grep -i yjit
RUBY_YJIT_ENABLE=1

Наличие переменной окружения не говорит вам ничего о том, запущен ли Ruby в данный момент с включённым YJIT. В данном конкретном случае переменная окружения установлена, но что-то другое перезаписывало переменную, которую Rails использует для включения (или отключения) YJIT при запуске. Другого объяснения тому, почему GlobalSetting.yjit_enabled= возвращает nil, даже на новом экземпляре Rails, нет. Также нет никаких причин, по которым YJIT должен быть отключён на новом экземпляре Rails.

После добавления переменной окружения DISCOURSE_YJIT_ENABLED в мой файл containers/app.yml:

  1. sudo -u discourse RAILS_ENV=production bundle exec rails runner 'puts "YJIT enabled: #{RubyVM::YJIT.enabled?}"; puts RUBY_DESCRIPTION' возвращает YJIT enabled: true
  2. Использование памяти на моём сервере наконец немного увеличилось.
  3. Я заметил реальное ускорение работы моего форума.

Должно быть легко воспроизвести мои результаты. Просто добавьте шаблон и проверьте.

Это неверно. На уровне Ruby переменная окружения является одним из официальных переключателей. См. официальную документацию Ruby по этой теме здесь:

Это неверно, так как DISCOURSE_YJIT_ENABLED лишь передаёт значение в GlobalSetting.yjit_enabledconfig.yjit в файле config/application.rb. Rails использует это для включения YJIT, если он ещё не включён. Он не отключает уже активный YJIT. Таким образом, когда переменная окружения установлена, DISCOURSE_YJIT_ENABLED ничего не делает.

Чтобы дополнительно подтвердить свою точку зрения, я написал плагин, который возвращает информацию о том, включён ли YJIT в моём веб-процессе:

https://discourse-on-a-pi5.falco.dev/ruby-info

Вы путаетесь в переключателе на уровне Rails, что излишне, так как следует использовать переключатель на уровне Ruby.

Хм! То есть вы говорите, что мы можем надежно использовать переменную окружения для определения, включен ли YJIT! Я об этом не знал; спасибо за ссылку на документацию Ruby.

Однако я немного запутался. Как это возможно, что env | grep RUBY_YJIT_ENABLE возвращает RUBY_YJIT_ENABLE=1, но новый экземпляр Rails в том же контейнере, когда его просят вывести #{RubyVM::YJIT.enabled?}, выводит false? Разве он не должен выводить true, поскольку, как вы упомянули, эта переменная окружения работает на уровне Ruby?

Вы, наверное, очень заняты, и это не должно иметь значения, так что отвечать не обязательно. Я должен суметь разобраться с этим на своем собственном сервере. Не могли бы вы поделиться своим плагином? Мне нужен способ быть уверенным, что мой сервер Discourse работает на Ruby с включенным YJIT.

Я отмечу ваш ответ как решение, как только воспроизведу ситуацию.

Заранее спасибо!

Извините, я разобрался.

sudo -u discourse очищает окружение. Использование флага -E сохраняет обычное окружение, и в этом случае sudo -E -u discourse RAILS_ENV=production bundle exec rails runner 'puts "YJIT enabled: #{RubyVM::YJIT.enabled?}"; puts RUBY_DESCRIPTION' возвращает

YJIT enabled: true
ruby 3.4.7 (2025-10-08 revision 7a5688e2a2) +YJIT +PRISM [x86_64-linux]

При добавлении только шаблона.

Приношу извинения за потраченное впустую время и отметил ваш ответ как решение. Извините за это. Спасибо за расследование и время, уделенное ответу.