RubyがいかにJITと向き合ってきたか
TLDR
Ruby under the Microscopeと言う本の輪読会をやっていて、JITまわりで気になった部分があったので、解説します。
今、有志でRuby under the Microscopeという本を輪読しています。
この本はRubyのしくみという邦題で訳されてもいて、Rubyが内部でどうやって動いているのか、とても丁寧に解説されています。
2014年にすでに本は出ていて、その頃に購入はしていたのですが、今まで積読していました。
JITとは何か
JITとは「Just in Time」の頭文字で、その名の通り「必要な分を、必要な時に」コンパイルするコンパイラのことです。
なぜ今読むのか
今週、Ruby edgeブランチにでYJITというRailsパフォーマンス向上が期待できる新しい種類のJITがマージされました。PRはこちら。たまたま、その開発者・チームと同じ会社(Shopify)で働いているので、今回一念発起して冒頭の本の輪読を始動することができました。
メンバーは
- freddi さんと
- tsuna さんです。
気になったところ
現在第二章を読み終わったところなのですが、
Ruby never compiles your Ruby code all the way to machine language. Ruby interprets the byte code instructions. > TheJVM, on the other hand, can compile some of the bytecode instructions all the way into machine language using its "hotspot" or just-in-time (JIT) compiler.
この部分が気になったので考えを整理してみました。
Ruby - JIT以前
RubyがJITを導入する前 (~ Ruby2.5) は、Rubyが生成するコードは、以下の翻訳を辿っていました。(Ruby under the Microscopeが書かれたときは、まだRuby2.5以前)
- あなたが書くRubyコード
- AST(抽象構文木)ツリー
- YARV命令文(バイトコード)
3.で生成された命令文を、Cで書かれたRuby VM(Virtual Machine)が実行時(ランタイム)にそのまま解釈することにより、プログラムが実行されていました。なので、気になった部分の「Ruby never compiles your Ruby code all the way to machie language...」という説明になるわけです。
JVMのJIT
一方で、JVMは、JVM用のバイトコードを解釈する際に、「場合によって」それを機械語まで訳してから、実行するという選択肢をとることができます。
JITコンパイラーは その際たる例で、「実行している環境に対応する形で」機械語に翻訳してから走らせるので、パフォーマンスの最適化が期待できます。
詳しくどういう場合に高速化が期待できるのかは、それだけで記事が書けます。本記事では、「実行時の情報(どんなコードがどれだけ走るか, ....)にアクセスできる柔軟さが売り」というくらいに留めておきます。
現在のRuby
YJITが稼働していない現状のRuby(Ruby3.0系)では、Ruby2.6で登場した「MJIT」というものが上記で解説したJVMのJITに相当する動きをしているので、冒頭の本の記述は、少し古くなっているという現状です。
MJITに関しては、それの作者の k0kubun さんが https://k0kubun.hatenablog.com/entry/ruby26-jit でサマリをしているので、どうかそちらを参照ください。
記事より、MJITの動作図。むずかしい。
じゃあ、「Rubyのしくみ」はすでに時代遅れ?
まったくそんなことはない、という印象です。逆に、本に書いてある部分が少し古くなっているとしたら、それはRubyが大幅に改善した箇所でもあるので、Rubyの最近の進化を学ぶ上で、この本で説明されたRubyの概要をベンチマークとして使うことに、大いに価値がありあmす。
そんなことを言う出すまでもなく、ここまで丁寧にRubyの実装を学ぶことができる本は他には見当たりません。良書です。
ぜひ、みなさんも一章、一章、パズルを解くように読んでみてください。
そして、みんなでJITで遊びましょう :)
あのTenderloveさんもJITで遊んでいるので、楽しいこと間違いなしですよ!
Discussion
Edit
MJITの記事を引用する際、誤って Sasadaさんの名前を記載しておりました。
k0kubun さんに正しく修正いたしました。
指摘してくださってありがとうございます。