🙆

Rails 7.1 + Ruby 3.3 で YJIT を有効化してパフォーマンス改善を行った結果

2024/03/18に公開

この記事の概要

こんにちは。PharmaX でエンジニアをしている諸岡(@hakoten)です。

この記事では、薬局DX事業部のバックエンドで採用しているRuby on Railsのアプリケーションについて、Rubyバージョンを3.3にアップグレードし、YJITを有効化した結果、どのようにパフォーマンスが向上したかをご紹介します。

現在のRuby on Railsのバージョンは、「7.1.3」になります。

YJITについての簡単な説明

YJITとは、CRuby内部に組み込まれた軽量のJIT機能で、遅延コード生成を行い、必要なメソッドを部分的にコンパイルすることで高速化を図る仕組みです。
(処理系は詳しくないため、ざっくりになってしまいすみません。。)

Ruby 3系列の主要な機能の一つであり、3.1で導入され、3.2で正式にサポートされ、3.3においてさらに安定化が行われています。

詳しい内容は、YJITのドキュメントやこのプレゼンテーションを参照ください。

YJITを有効にした経緯

YJITはコンパイラの特性上、マシンコードやメタデータをメモリ上に保持するため、通常のインタプリタに比べてより多くのメモリを消費する傾向があります。

https://github.com/ruby/ruby/blob/ruby_3_3/doc/yjit/yjit.md#reducing-yjit-memory-usage

(参考リンク)
https://k0kubun.hatenablog.com/entry/tuning-yjit

このメモリ使用量を警戒して、YJITに注目はしていましたがRuby3.2の時点で有効にすべきか迷っていました。
しかし、2023年12月にリリースされたRuby 3.3では、メモリ使用量が大幅に改善されたため、すぐに導入することを決めました。


Memory usage on benchmarks

https://railsatscale.com/2023-12-04-ruby-3-3-s-yjit-faster-while-using-less-memory/

ちなみに、 Ruby On Rails 7.2からはYJITがデフォルトで有効になります。

https://github.com/rails/rails/commit/c29cda2fec6035f478424628514e166fe07f8d3b

YJITをRailsで有効にする

YJITの有効化は、こちらのRails7.2の対応を参考に次のように実装しています。

config/initializers/enable_yjit.rb
if defined? RubyVM::YJIT.enable
  Rails.application.config.after_initialize do
    RubyVM::YJIT.enable
  end
end

有効になっているかどうかは、次のコマンドで確認できます

bin/rails r 'p RubyVM::YJIT.enabled?'

その他留意事項としては、Ruby3.3にアップグレードする際に対応していないライブラリがいくつかありました。これらのアップグレードを待っていたため、現在までリリースが遅れてしまいました。

Ruby3.3でYJITを試したい場合は、プロジェクトで使っているライブラリが対応しているかどうかも確認しておくと良いでしょう。

パフォーマンスの確認

レスポンス時間

前後10日を比較した時の平均のレスポンス時間は、約25% 向上していました。
ピークの時間帯では45%程度早くなっている箇所も確認できました。

比較的外部要因の影響を受けにくいRuby処理がメインのAPIを見ると、顕著にパフォーマンスの差が出ており、最も影響がわかりやすいAPIだと約50%高速になっているものもありました!

メモリ使用量

懸念されていたメモリ使用量についても、問題はありませんでした。
Ruby3.3にアップグレードした結果、10% ~ 20%程度の上昇を見込んでいましたが、実際のデータでは約5%程度下がっています。

CPU使用率

CPU使用率についてもリリース前後で大きく問題は発生していません。

終わりに

結果として、全体で約25%前後、Rubyメインの処理では最大約50%程度の高速化が確認できました。

簡単な対応でこれだけのパフォーマンス向上が達成でき、大変満足しています。またRuby開発者の皆様の努力に感謝しています。

心配していたメモリ使用量についても大きな問題は発生しておらず、Ruby3.3からの導入であれば積極的に導入しても良いかと思います。弊社他アプリケーションでも徐々に反映させていく予定です。

PharmaX では、様々なバックグラウンドを持つエンジニアの採用をお待ちしております。
もし、興味をお持ちの場合は、私の X アカウント(@hakoten)や記事のコメントにお気軽にメッセージいただけますと幸いです。まずはカジュアルにお話できれば嬉しいです!

参考記事

https://k0kubun.hatenablog.com/entry/ruby-3-3-yjit
https://engineering.dena.com/blog/2023/12/voice-pococha-yjit/

PharmaXテックブログ

Discussion