Matz氏のSpinel登場 — Ruby AOTネイティブコンパイラが切り開く11倍高速化の世界

はじめに

Rubyの生みの親、まつもとゆきひろ(Matz)氏が2026年4月、個人リポジトリで Spinel(スピネル) という新しいAOT(Ahead-of-Time)ネイティブコンパイラを公開した。Hacker Newsでは261ポイントを獲得し、Ruby界隈だけでなく広くプログラミング言語コミュニティで話題となっている。本記事では、SpinelがCRubyと何が違うのか、どういう仕組みで「11.6倍高速」を実現しているのか、そしてRuby言語そのものの未来にどんな影響を与えうるのかを、Matz氏自身の公開情報とHacker Newsでの議論を踏まえて深掘りする。

Spinelとは何か — Rubyを単体バイナリへ

Spinelは、Rubyのソースコードを スタンドアロンのネイティブ実行ファイル にコンパイルするAOTコンパイラだ。既存のCRuby(MRI)がソースをバイトコードに変換し仮想マシン(YARV)で逐次実行するのに対し、Spinelはソースを直接Cコードに変換し、標準Cコンパイラで最適化フラグ付きでコンパイルする。生成されたバイナリは libc と libm のみに依存 し、実行時にRubyランタイムを必要としない。

技術的な構成要素は次の3段階だ。

  1. パーサ: 既存のRuby公式パーサであるPrismを使ってソースコードをASTに変換
  2. コード生成: spinel_codegen がプログラム全体の型推論を実行し、最適化されたCコードを出力
  3. ネイティブコンパイル: 標準のCコンパイラ(GCC/Clang)で最終バイナリを生成

注目すべきは、Spinel自身が 自己ホスティング(self-hosting)を達成している点だ。コンパイラのバックエンド(spinel_codegen.rb)はSpinel自身がコンパイルできるRubyサブセットで書かれており、最初のブートストラップ以降はCRubyなしでパイプライン全体が動く。これは言語実装プロジェクトにとって、実装言語としての完成度を示す重要なマイルストーンである。

リポジトリは MITライセンス、Ruby 70.5% / C 28.4%、バックエンドのコード規模は約21,000行と比較的コンパクト。すでに公開段階で849スター/10フォーク、74個のテストと55個のベンチマークが通過している。

なぜ11.6倍も速くなるのか — 全プログラム型推論と値型最適化

Spinelの公称性能は、28ベンチマークの幾何平均で miniruby(Ruby 4.1.0dev)の約11.6倍。個別のベンチマークでは次のような値が報告されている。

  • Conway’s Game of Life: 86.7倍
  • Ackermann関数: 74.8倍
  • Mandelbrot: 58.1倍
  • フィボナッチ再帰: 34.2倍
  • JSON解析: 10.1倍
  • レイトレーサー: 8.0倍

この速度差はどこから来るのか。鍵は whole-program type inference(全プログラム型推論) と、それに続く複数の最適化である。

  • 値型昇格(value-type promotion): フィールド数が8以下の小さな不変クラスはヒープではなくスタックに割り当てられ、GCオーバーヘッドが消える
  • 定数伝播: リテラル定数はコンパイル時にインライン化される
  • 文字列連結の平坦化: "a" + b + c のような連結は単一のメモリ割り当てに畳み込まれる
  • Bigint自動昇格: ループ内の乗算・加算から桁あふれの可能性を静的に検出し、必要な箇所だけBigintに切り替える

これらはCRubyがJITコンパイラ(YJIT / RJIT)で一部実現しつつあるものの、実行時プロファイルに依存しない静的解析 でやり切る点がSpinelの特徴だ。JITは「実行してから温まるまでの時間」が避けられないが、AOTは起動直後から最適化済みのコードが走る。CLIツールやサーバレス関数のような短命プロセスでは、この差が大きな意味を持つ。

類似の試みは過去にも存在した。mrubyは組み込み向けの軽量実装、TruffleRubyはGraalVM上のJIT最適化、JRubyはJVM上の実行と、それぞれ別のアプローチで高速化を狙ってきた。SpinelはC生成×全プログラム型推論という古典的AOTの王道を進んでおり、Ruby本体に近い文法適合性 と 依存の少ないバイナリ を同時に狙える点が差別化要因になっている。

エンジニアへの影響 — どこで使えて、どこで使えないか

ここは冷静に見る必要がある。Spinelは強力だが、現段階では Rubyのサブセットしかサポートしていない。README記載の制限事項は以下の通り。

  • eval 非対応
  • メタプログラミング(send、method_missing など)非対応
  • スレッド非対応
  • 文字エンコーディング対応なし

つまり、Ruby on RailsのようにActiveRecordが動的にメソッドを生やしたり、method_missing でプロキシを実装したりするコードは今のところ動かない。Rubyの「動的さ」を前提にしたフレームワークやDSLはターゲット外と考えるのが現実的だ。

一方で、Spinelが刺さりそうな領域は明確にある。

  1. CLIツール: Rubyで書かれたコマンドラインツール(Rubocop、HaML など系譜)は起動オーバーヘッドが常に批判されてきた。AOTで単体バイナリ化できれば、Goで書き直す動機がひとつ減る
  2. サーバレス関数: コールドスタート時間が課金に直結するLambda系ワークロードでは、起動速度の差が直接コストに効く
  3. 組み込み/エッジ: libc依存のみなら、Raspberry Pi やエッジデバイスでRubyコードを動かす選択肢として現実味がある
  4. 計算集約的バッチ処理: JSONパース10倍、レイトレース8倍という数字は、データ処理バッチでCRubyを置き換える十分な理由になる

逆に、Rails本体や既存の複雑なgemが依存するコードをそのまま通すのは現時点では難しい。Spinelは「Rubyの速いサブセット」として位置付け、適材適所で使うのが正解だろう。

まとめ

  • MatzがAOTコンパイラSpinelを公開、CRubyの 平均11.6倍 という性能を記録
  • 全プログラム型推論とC生成による古典的AOTアプローチで、起動直後から最適化済みコードが走る
  • 自己ホスティング達成、MITライセンス、libc/libm のみ依存という実用性重視の設計
  • 一方で eval・メタプログラミング・スレッド・エンコーディングは未対応で、Rails系ワークロードは対象外

Rubyは長らく「書きやすいが遅い」と言われ続けてきたが、YJITの躍進に続くSpinelの登場は、言語の表現力を維持しつつ速度の天井を押し上げる動きだ。今後Spinelがどこまで仕様カバレッジを広げ、あるいはCRubyそのものに取り込まれていくのか、Ruby 4.x 時代の焦点のひとつになりそうだ。

ソース