こんにちは、
私はセルフホスト型の Discourse インストール(2026.5.0-latest)を運用しています。本日、YJIT を有効にしようと試みました。containers/app.yml に "templates/enable-ruby-yjit.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]
enable-ruby-yjit.yml テンプレートを追加したにもかかわらず、YJIT は有効になっていませんでした。その後、sudo -u discourse RAILS_ENV=production bundle exec rails runner 'puts "GlobalSetting.yjit_enabled=#{GlobalSetting.yjit_enabled}"' を実行すると、GlobalSetting.yjit_enabled= という出力が得られ、値は nil でした。
いろいろと試行錯誤した結果、最終的に containers/app.yml に以下の設定を追加することで YJIT を有効化できました:
env:
DISCOURSE_YJIT_ENABLED: true
どこかにバグがあることは間違いありません(GlobalSetting.yjit_enabled が nil を返すべきではありません)。しかし、環境変数を設定することで解決しました。このトピックを検索している誰かの助けになれば幸いです。
Falco
(Falco)
2
それは誤った診断ではありませんか?実際に Web サーバーを稼働している Ruby プロセスではなく、新しく生成された Ruby プロセスの ENV を確認しています。
Pitchfork モールドプロセスの /proc/<pid>/environ を確認すると、そこに YJIT 環境変数が存在していることがわかります。
root@raspberrypi5:/var/discourse# cat /proc/3331660/environ | tr '\0' '\n' | grep -i yjit
RUBY_YJIT_ENABLE=1
環境変数の存在を確認しただけでは、Ruby が現在 YJIT を有効にして実行されているかどうかはわかりません。この特定のケースでは、環境変数が設定されていましたが、起動時に Rails が YJIT の有効化(または無効化)に使用する変数を別の何かが上書きしていました。新しい Rails インスタンスでも GlobalSetting.yjit_enabled= が nil を返す理由を他に説明する方法はありません。また、新しい Rails インスタンスで YJIT が無効になる理由もありません。
containers/app.yml に DISCOURSE_YJIT_ENABLED 環境変数を追加した後、
sudo -u discourse RAILS_ENV=production bundle exec rails runner 'puts "YJIT enabled: #{RubyVM::YJIT.enabled?}"; puts RUBY_DESCRIPTION' を実行すると、YJIT enabled: true が返されます。
- サーバーのメモリ使用量がようやくわずかに増加しました。
- フォーラムで実際に速度向上が見られました。
私の発見を再現するのは簡単です。テンプレートを追加して確認してみてください。
Falco
(Falco)
4
これは誤りです。Ruby レベルでは、この ENV 変数は公式の切り替え手段の一つです。詳細は Ruby の公式ドキュメントをご覧ください。
これも誤りです。DISCOURSE_YJIT_ENABLED は GlobalSetting.yjit_enabled → config/application.rb 内の config.yjit にのみ影響を与えます。Rails は、YJIT がまだ有効になっていない場合にのみ、この設定を使って YJIT を有効化します。すでに有効になっている YJIT を無効化するものではありません。したがって、環境変数が設定されていても、DISCOURSE_YJIT_ENABLED は何の役割も果たしません。
私の主張をさらに証明するために、Web プロセスで 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 になるのはどうしてでしょうか?あなたが言及された通り、この環境変数は Ruby レベルで機能するはずです。だから true が出力されるはずです。
おそらくあなたは非常に忙しく、この件は重要ではないでしょうから、回答する必要はありません。自分のサーバーで自分で解決できるはずです。もしよろしければ、あなたのプラグインをいただけますか?Discourse サーバーが YJIT 有効化された Ruby で実行されていることを確実に確認する方法が欲しいのです。
再現を確認した後、あなたの回答を解決策としてマークします。
事前に感謝します!
申し訳ありません、解決しました。
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]
という結果が返ってきます。
テンプレートのみを追加した状態です。
お時間を無駄にしてしまい申し訳ありません。ご回答を解決策としてマークいたしました。お手数をおかけしてすみません。調査とご回答に時間を割いていただき、ありがとうございます。