YJITは、Ruby 3.1から標準搭載されたJITコンパイラだ。ShopifyとRubyコアチームが共同で開発し、Shopifyの本番環境で鍛えられてきた実績がある。
JITとは何か(おさらい)
Rubyは通常、インタープリタがコードを1行ずつ読み取って実行する。
Rubyコード → インタープリタが読んで → 1行ずつ実行
毎回「読んで解釈して実行」を繰り返すので、それなりにオーバーヘッドがかかる。
JIT(Just-In-Time コンパイラ) はこれを改善する仕組みだ。
Rubyコード
↓ 何度も呼ばれるコードを検出
↓ そのコードをCPUが直接実行できる「機械語」に変換
→ 次回以降は高速な機械語で実行
YJITの特徴:「使いながら賢くなる」
YJITの面白い点は動かしながら学習するところだ。
def add(a, b)
a + b
end
add(1, 2) # 最初はインタープリタで実行
add(3, 4) # 何度も呼ばれると…
add(5, 6) # YJITが「このメソッドは頻繁に使われる!」と判断
# 機械語にコンパイルして高速化
さらに「型の推測」も行う。
# addが毎回Integerで呼ばれていると学習したら
# 「次もIntegerだろう」と仮定した最適なコードを生成
仮定が外れた場合でも、インタープリタに安全に戻れる仕組みが用意されている。これをサイドエグジットと呼ぶ。
どのくらい速くなるの?
| 環境 | 効果 |
|---|---|
| Shopify本番環境 | 約20〜25%高速化 |
| Discourse | 約10〜20%高速化 |
| Railsベンチマーク | 平均15〜20%高速化 |
長時間動くサーバーアプリほど恩恵が大きい。起動直後はまだコンパイルが進んでいないため、ウォームアップが必要なためだ。
使い方は簡単
# フラグをつけるだけ
ruby --yjit app.rb
# Railsなら
RUBY_YJIT_ENABLE=1 bundle exec rails s
Ruby 3.3以降はデフォルトで有効になっているため、何もしなくても恩恵を受けられる。
YJITとZJITの違い
ZJITの記事でも触れたが、改めて整理する。
YJIT(Ruby 3.1〜)
├ 今すぐ使える・安定している
├ Shopify等で本番稼働中の実績あり
└ Ruby 3.3からデフォルト有効
ZJIT(Ruby 4.0〜 experimental)
├ YJITの後継として開発中
├ メソッド全体をコンパイル単位とし、SSA-IRで最適化
└ まだ本番利用は非推奨
現時点では YJIT = 使える・速い・安定、ZJIT = 将来への投資 という位置づけだ。
まとめ
YJIT = Rubyを速くする仕組みで今すぐ使えるもの
- Ruby 3.3からデフォルト有効(意識しなくてもOK)
- 長時間動くRailsアプリで特に効果大
- Shopifyが開発・実績あり
- 難しい設定不要、
--yjitフラグだけで試せる
参考文献・リンク
https://shopify.engineering/yjit-just-in-time-compiler-cruby
https://github.com/ruby/ruby/blob/master/doc/yjit/yjit.md
https://www.ruby-lang.org/en/news/2021/12/25/ruby-3-1-0-released/
https://www.ruby-lang.org/en/news/2023/12/25/ruby-3-3-0-released/