UnderdogのRuby YJIT
Underdogでは、多くのプロジェクトがRailsサービスです。そこでRuby 3.2.0がリリースされたときには、早速実践して、この最新バージョンでどれだけパフォーマンスを向上できるか確認するのが楽しみでした!この投稿では、リリースの中でも重要な変更点とそのパフォーマンスへの影響について議論します。
伝統に従い、Ruby 3.2.0はこのクリスマスにリリースされました。この言語の一歩前進として、以下の最適化が含まれています:
- 可変幅メモリアロケーション
- オブジェクト形状
- 商用利用可能なYJITコンパイル
ShopifyはRubyの前進をリードする役割を果たしており、このリリースがその証拠です。彼らはリリースの数日前からYJITを商用環境で実行しており、その厳密さから私たちは、いくつかの簡単なテストを経た後、自社の商用環境に3.2.0を導入することに快適さを感じました。
アップグレードの方法
アプリのコンテナでYJITを有効にしたいと思ったとき、私たちはRubyの公式のDebianベースのイメージを使っていました。残念ながら、その時点ではこれらのイメージにYJITのサポートは含まれていなかったため[^1]、代わりにRubyのAlpineベースのイメージにコンテナのイメージを切り替えることにしました。Debianベースのイメージを使っていたのは安定性のためでしたが、Debianの一般的な方針により古くなった他のパッケージでも問題が発生していたので、Alpineに切り替えることで追加の利点が得られました。
ここでの作業量は少なかったです。Dockerfileを変更し、二つのディストリビューション間でシステムレベルの依存関係名を更新し、続いてアプリのコンテナ用のKubernetesマニフェストにRUBY_YJIT_ENABLE
環境変数を追加するだけでした。デプロイメントでその値を1
に切り替えた後、コンテナ内に入ってruby —-version
でYJITが有効になっていることを確認することができました。
結果
Ruby 3.2.0をサポートするために更新する必要のあるサードパーティ依存関係がいくつかありましたが、それらの変更を行った後、物事は順調に進みました。週末に問題や驚きはなく、全体として応答時間が約10%減少しました:
p50では約9%の改善が見られ、p98では12.5%にまで向上しました。これは興味深く、Railsに対するこのアップデートの影響を期待していた通りでした。最速のAPIは、データベースIOに多くの時間を費やしているため最適化の余地が少ないですが、パフォーマンスの悪いAPIは、Rubyでのより多くのロジックか、より大きなオブジェクトのシリアライズをよく行っています。このようなよりRubyに依存するリクエストに最大の改善を見込んでいて、Rubyが多用されるAPIを選んでこれを裏付けました。
以下は私たちの下書きAPIで、下書きエントリとピックをシリアライズしています。シリアライズすべきデータよりも多く、実行すべきロジックよりも多いですが、我々のSLOよりも下なので、まだ最適化していません。
この改善は驚異的です。この比較では、最もパフォーマンスの悪いシナリオで最大の改善が見られました。これは素晴らしいことです!
Underdogでは、Sidekiqを介してバックグラウンドジョブで統計を処理し、コンテストを評価しています。私たちは、ジョブ実行時間が改善されたかどうかも気になっていました...確かに、改善されました!
p90は少し奇妙に見えますが、それ以外では大幅な改善が見られました。これも理にかなっています。Rubyを多用するプロセスがバックグラウンドジョブに変えられることは一般的だからです。
結論
プロジェクトを常に最新の状態に保って、最新リリースのメリットを活用することが非常に重要で、特にUnderdogが3.2.0にアップグレードするのがいかに簡単だったかを考えると、無料のパフォーマンスを得ることができます。しばらくの間、RubyはRailsデプロイの観点から交錯する結果でパフォーマンスアップグレードを約束してきましたが、3.2.0で大きな一歩を踏み出しました。Rubyコアチームは大活躍で、この言語の背後にこんなに強力なチームがいることは私たちの幸運です。
Underdogでの私たちのチームについてもっと知りたいですか?こちらの文化とキャリアページをチェックして、私たちがゲームをどのように変えているかを見てください!
こちらの記事はdev.toの良い記事を日本人向けに翻訳しています。
https://dev.to/underdogsports/ruby-yjit-at-underdog-5629