템플릿으로 YJIT를 활성화하면 작동하지 않습니다

안녕하세요,

저는 자체 호스팅(self-hosted)된 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을 반환해서는 안 됩니다). 하지만 환경 변수를 설정하는 방식으로 작동했고, 이 문제를 검색하는 분들이 이 주제를 찾기를 바랍니다.

그건 오진(誤診)이 아닌가요? 실제 웹 서버를 실행 중인 프로세스가 아니라, 새로 생성된 ruby 프로세스의 ENV를 확인하고 있습니다.

Pitchfork의 mold 프로세스의 /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가 꺼져 있을 이유도 없습니다.

컨테이너의 app.yml에 DISCOURSE_YJIT_ENABLED 환경 변수를 추가한 후,

  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 레벨에서 ENV 변수는 공식적인 토글 중 하나입니다. 이에 대한 Ruby 공식 문서를 여기서 확인해 보세요.

이것도 잘못되었습니다. DISCOURSE_YJIT_ENABLED는 오직 GlobalSetting.yjit_enabledconfig/application.rbconfig.yjit에만 공급됩니다. 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가 나오는 것이 어떻게 가능한가요? — 당신이 언급했듯이 이 환경 변수는 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]

템플릿만 추가했을 때의 결과입니다.

귀하의 시간을 낭비하게 해서 죄송합니다. 그리고 귀하의 답변을 해결책으로 표시했습니다. 이런 일이 있어서 죄송합니다. 조사해 주시고 답변해 주신 시간 덕분에 감사합니다.