12月25日は何の日でしょうか。そう、Rubyの新バージョンがリリースされる日、クリスマスです。
今年も例年通りRuby 3.3.0 がリリースされました。
Ruby 3.2.0 以降では5532 個のファイルに変更が加えられ、326851 行の追加と 185793 行の削除が行われました、とのことでリリース記事には多くの変更点が記載されています。
この変更点の一つにYJITが挙げられていますが、その中に気になる記載があります。
コマンドライン引数や環境変数を変更せずにYJITを開始できます。Rails 7.2はこの方法を使用して デフォルトでYJITを有効にします。
Ruby 3.3.0 リリース
今回は、Ruby 3.3.0とRailsの関係を探り、そして新機能を早速試してみたいと思います。
※このコラムのプログラム等は以下の環境で動作確認しています
(2023/12/31 最終確認)
ruby: ruby 3.3.0 [arm64-darwin22]
rails: rails (7.1.2)
YJIT
そもそもYJITとは何でしょうか。
YJIT (Yet Another Ruby JIT) はShopifyにより開発されたプロセス内JITコンパイラで、Ruby 3.1でリリースされました。
Yet Anotherを称する通り、従来のRuby JITコンパイラ、MJITを代替するものとして導入されています。
MJITはRuby 3の目標、Ruby 2の3倍速くする「Ruby3x3」実現の立役者でしたが、「Railsのような様々なメソッドを満遍なく呼び出す」状況での性能の改善には至っていませんでした。(Ruby 3.0.0)
Shopifyは巨大なeコマースプラットフォームとして、そして世界有数のRailsアプリケーションとして知られており、YJITはこれを高速化するために開発されました。
YJITを利用するとアプリケーションの素早い起動と高速な実行がもたらされるとされています。
JIT
「その前に、JITコンパイラって何…?」という方もいらっしゃるかも知れません。
(コンピューターの世界での)コンパイラとは、私たちが普段書いているRubyのような人間にとって扱いやすいプログラミング言語(高水準言語、高級言語)を、コンピューターが処理できる形式に変換する仕組みです。
JIT(Just In Time)コンパイラ、実行時コンパイラとはソフトウェアの実行時にこの処理を行うことを示します。
高水準言語をコンピューターで実行するためには、このような変換が必ず行われますので、この変換部分を改善することでアプリケーションの性能を大きく改善することができる、ということになります。
コンパイラの話題は大変奥深いためこれ以上の紹介は割愛しますが、興味のある方は是非調べてみてください。
RubyVM::YJIT.enable
そんなYJITですが、リリースされた3.1時点では「実験的な機能」とされており、Ruby本体に取り込まれてはいるもののオプションで明示的に有効にしない限り利用されない、という状態になっています。
この「オプション」は、Ruby起動時に明示的にコマンドラインオプションを与える必要がある、というものでした。
それが今回、Ruby 3.3ではRubyVM::YJIT.enable
というメソッドを呼び出すことで任意のタイミングで有効化できるようになりました。
この仕組みを利用し、Railsアプリケーションの起動時、つまりinitializers内でYJITを有効にする、という対応が「Rails 7.2はこの方法を使用して デフォルトでYJITを有効にします。」です。
Rubyのリリース記事にはRailsのPull Requestが記載されていますが、こちらを追っていくとRubyのPull Requestが記載されており、元々DHHの興味が発端で実装された機能ということが読み取れます。
デフォルト化の前に先取り!
このデフォルト化が取り入れられるのは7.2のリリースタイミングとなりますが、Pull Requestに記載されている通りにinitializerを導入すれば有効になるはずです。
ということで、試してみましょう。
いつも通りにrails new
して新しいRails アプリケーションを作成し、適当なControllerとViewを作成、YJITの状態を表示してみます。
app/views/top/show.html.erb
<p>
RubyVM::YJIT.enabled? : <%= RubyVM::YJIT.enabled? %>
</p>
false
と表示されました。
initializersへ追加
Railsの Pull Requestを参考にしてinitializersにファイルを追加します。
config/initializers/enable_yjit.rb
if defined? RubyVM::YJIT.enable
Rails.application.config.after_initialize do
RubyVM::YJIT.enable
end
end
サーバーが起動中であれば一旦停止し、サーバーを起動して再度ページを表示してみます。
true
と表示されました。
YJITが有効になったことを確認できました。簡単ですね。
注意: メモリ使用量
こうしてYJITは簡単に有効化できますが、高速化される一方でメモリ使用量が増大します。
既存のアプリケーションに導入する場合はご注意ください。
まとめ
Ruby 3.3.0 と Rails の関係を探り、Rubyの高速化の仕組みであるYJIT、そしてRuby 3.3で導入されたYJITを簡単に有効化する仕組みとRailsへの導入についてご紹介しました。
必ずしも高速化に繋がるとは限りませんが、今後デフォルトで有効化されることを踏まえますと、新規のアプリケーションを作成する場合は今から有効化しておくことで恩恵を先取りできるかも知れません。
なお、既にYJITを導入された方々もおり、先行事例はインターネット上でもいくつか確認することができますので参考にしてみてください。
折角進歩し続けるRubyを使っているのですから、是非皆さんの環境でも取り入れてよりよいアプリケーション環境に繋げていきましょう。
お知らせ
当委員会ではRails試験を全国300か所で一年中実施をしています。興味がある方は以下をご覧の上、是非受験ください。https://railsce.com/exam