Ruby 3.2.0dev にマージされた Rust YJIT をビルドする

YJIT の Rust 実装がマージされました。いまのところ今年の Shopify からの代表作ではと見ています (YJIT 自体は Ruby 3.1 で C 実装導入されている機能です) 。

github.com

そういうわけで、現在の Ruby 3.2.0dev で YJIT を有効にする場合は、Rust の処理系 (1.60.0 1.58.1 以上) が必要になります。Rust のインストールに使う rustup については以下の公式ページなどを参照してください。

www.rust-lang.org

YJIT はデフォルトではビルドされません (なので YJIT を使わないビルドであれば Rust 処理系は不要です) 。

デフォルトの YJIT なしの Ruby をビルドしている場合は --yjit オプションを渡しても、ruby: warning: Ruby was built without YJIT support と以下のように警告が出力されます。YJIT の API は存在しないので、使おうとするとエラーになります。

% ruby --yjit -e 'p RubyVM::YJIT.enabled?'
ruby: warning: Ruby was built without YJIT support
-e:1:in `<main>': uninitialized constant RubyVM::YJIT (NameError)

p RubyVM::YJIT.enabled?
        ^^^^^^

このあたり Ruby 3.1 と異なるデフォルト (のビルド) 挙動なので、YJIT を有効にしているユーザーは気に留めておくと良さそうです。

% ruby --yjit -ve 'p RubyVM::YJIT.enabled?'
ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) +YJIT [x86_64-darwin19]
true

Ruby 3.2.0dev において、YJIT 込みで Ruby 本体をビルドする場合は以下のように ./configre にオプションを渡します。

% ./autogen.sh
% ./configure --enable-yjit=dev ...
% make -j install
building Rust YJIT (dev mode)
% ruby --yjit -ve 'p RubyVM::YJIT.enabled?'
ruby 3.2.0dev (2022-04-27T15:00:54Z master b43eb54a0c) +YJIT [x86_64-darwin19]
true

リリースモード --enable-yjitデバッグ開発モード --enable-yjit=dev でオプションが異なります。詳しくはドキュメントを参照してください。

github.com

rbenv を使っているようであれば、環境変数 RUBY_CONFIGURE_OPTS を使ったオプション渡しが手早いです。

% RUBY_CONFIGURE_OPTS=--enable-yjit rbenv install 3.2.0-dev
% ruby --yjit -ve 'p RubyVM::YJIT.enabled?'
ruby 3.2.0dev (2022-04-27T15:00:54Z master b43eb54a0c) +YJIT [x86_64-darwin19]
true

さらに Ruby のランタイムでも YJIT はデフォルト無効なので、YJIT を有効化する場合は ruby コマンドのオプションに --yjit を渡すか、環境変数 RUBY_YJIT_ENABLE=1 なんかを渡します。直接 ruby コマンドを使わずに rake 経由なんかで実行する場合は環境変数の指定方法を使うことになると思います。

あと当然ですが、Ruby のビルド環境に Rust がインストールされていなければ、YJIT 有効のビルド時に以下のようなエラーになります。

% RUBY_CONFIGURE_OPTS=--enable-yjit rbenv install 3.2.0-dev
(snip)

Last 10 log lines:
checking whether -pie is accepted as LDFLAGS... yes
checking whether wrapper for LD_LIBRARY_PATH is needed... no
checking whether dtrace USDT is available... no
checking for __builtin_setjmp... yes with cast ()
checking for _setjmpex as a macro or function... no
checking for _setjmp as a macro or function... yes
checking for sigsetjmp as a macro or function... no
checking for setjmp type... __builtin_setjmp
checking for rustc... no
configure: error: rustc is required. Installation instructions available at https://www.rust-lang.org/tools/install

Rust 処理系をインストールしましょう。

コード的には ruby/yjit ディレクトリ以下が、Rust の世界になっているようで、興味のある人は見てみると発見があるかもしれません。

github.com

RubyGems にも Rust 拡張に向けた Cargo ビルダーがマージされたこともあり、Ruby エコシステムと Rust との関わりが今後の関心どころです。

github.com

そういった流れもあるので、個人的には The Rust Programming Language (日本語訳) の後に『プログラミング Rust 第2版』を読んでいるところですが、痒い所に手が届く感じでおすすめです (先に The Rust Programming Language で全体の雰囲気を掴んでおくと理解がスムースかも) 。

🦀