はじめまして。ミツカリでエンジニア(ミドルくらい)をやっていますawagakubo(粟ヶ窪)といいます。 今回は弊社のバックエンド環境で採用しているRubyでYJITを有効化してパフォーマンスの向上を図った記録です。
背景
これはふとしたタイミングなんですが、YJITを有効化しているか確認したときにされていないことが発覚し、 現在のYJITのバージョンが3.4で安定しているだろうということから有効化してみようということになりました。
YJITについて
そもそもYJITとはなんぞやについてですが、既にYJITの知名度はそこそこ高く、関連記事も多いと思いますので簡単な紹介をします。
YJIT は、CRuby 内に構築された軽量で最小限の Ruby JIT です。Basic Block Versioning (BBV) アーキテクチャを使用してコードを遅延コンパイルします。(公式ページから引用)
要は、インタプリタ型言語のRubyをコンパイルしておくことで実行速度を速くしようというものです。 既に多くの企業でパフォーマンス改善の成果を上げており、弊社でも期待が持てるというものです。 特にバージョン3.3以降ではそれまで課題であったメモリ使用量が大幅に改善されたのもあり、有効化するプロジェクトが増えているのではないかと思います。
やったこと
とてもシンプルです。以下をinitializersにおいておくだけです。
if defined? RubyVM::YJIT.enable Rails.application.config.after_initialize do RubyVM::YJIT.enable end end
コンテナに入って有効化されていることを確認
>RubyVM::YJIT.enabled? => true
これでOKです。
ちなみに、YJITを有効化するためにはYJIT付きでコンパイルされたRubyが必要になるのですが、DockerのRubyイメージは標準でついているので楽でした。 一方localでrbenvを利用していて、localでも有効化したい場合はYJIT付きのrubyをインストールするためにrustをインストールしておく必要があったりします。
変化を確認
では、実際に有効化前後での変化を見ていきましょう。CPUとメモリの使用量、レスポンスタイムの3つを見ていきます。 YJITを有効化したのは2月19日の午前中ですので、その前後を比較していきます。
CPU使用量とメモリ使用量
まず、この2つについて見ていくとリリースから少し経ってから急激に利用量が上がっていることがわかります。 実はこれはYJITの影響ではなく、弊社のCTOつかびーがパフォーマンスチューニングを行った影響によるものです。(記事がこちらにあるのでぜひ読んでみてください。) このパフォーマンスチューニングは21日の10時ごろにリリースされたものですのでその間の短い間を見る必要があります。
パフォーマンスチューニングを分岐点としてみる
21日を分岐点としてみました。すると、分岐点を超えるまではそれほど各使用量は変わってないように見えますね。 特にメモリも変化が少ないと予想できそうなのはYJIT3.4のおかげのように思います。
レスポンスタイム
では、肝心のレスポンスタイムです。このレスポンスタイムの計測区間はロードバランサーを出てバックエンドで処理されて返ってくるまでの時間です。
ぱっとみですが、分岐点から下がってきているように見えますね。 先程のパフォーマンスチューニングの影響も考えられますが、特段負荷もかかっているわけでもなかったので普段のレスポンスタイムが速くなっていると考えられます。
どのくらい変わったかも少し確認しやすくするために、レスポンスタイムの累積和で見ていきます。
前4週間
後4週間
p95では、1分34秒 → 1分18秒 約17%の改善
p99では、2分5秒 → 1分39秒 約21%の改善
というふうに速くなっていることがわかります。また、この間のリクエスト数も前後で大きな違いはなく(むしろ少し後のほうが多いくらい)より効果が実感できます。 特にパーセンタイル4%分の重い処理であろう箇所でより速くなっているのではないかと考えることができ、他企業の報告に近しい結果でYJITの威力が発揮されているのではないかと考えられます。
というわけで、YJITの導入は成功し無事利用者のUX向上に貢献することができたのかなと思います。
最後に
今回の例を1つに、ミツカリではパフォーマンスを意識した施策も取り入れています。 もっともっと利用者を増やしていきたいので、今後もこの活動は続けていきていですね。 では、最後まで読んでいただきありがとうございました!
現在、ミツカリではITエンジニアを募集しています。興味のある方はぜひお気軽にご連絡ください!