概要
Spinel はRubyコードを ネイティブ実行ファイル にコンパイルするAOTコンパイラ。 全プログラム型推論 とCコード最適化で CRubyより高速 な実行を実現。 自己ホスティング 対応:自身のバックエンドもRubyで記述し自身でコンパイル。 多くのRuby機能 をサポートし、独自の最適化や組み込みランタイムを搭載。 依存性最小、高速ビルド、豊富なベンチマーク結果を公開。
Spinelの概要
- Spinel はRubyソースコードを スタンドアロンなネイティブバイナリ に変換するAOTコンパイラ。
- 全プログラム型推論 を用い、最適化されたCコードを生成。
- CRuby と比較して、計算負荷の高い処理で 大幅な高速化 を実現。
- 自己ホスティング :Spinel自身のバックエンドもRubyで記述し、Spinelでコンパイル可能。
- 依存性最小 :生成バイナリは libcとlibm のみ必要、外部ランタイム不要。
動作フロー
- Rubyファイル(.rb)を Prism でパースし、ASTをテキスト形式で出力。
- spinel_codegen で型推論とCコード生成を実施。
- 標準Cコンパイラ(gccなど)で ネイティブバイナリ をビルド。
- 生成されたバイナリは 完全スタンドアロン、Ruby環境不要。
クイックスタート
make depsで libprism 取得。makeで全体ビルド。- Rubyプログラム(例:hello.rb)を作成。
./spinel hello.rbでバイナリ生成、./helloで即実行。- オプションで出力ファイル名指定(-o)、Cコードのみ生成(-c)、Cコード出力(-S)など。
自己ホスティングとブートストラップ
- Spinelは自身のバックエンド(spinel_codegen.rb)を 自己コンパイル。
- ブートストラッププロセス:
- CRuby+spinel_parse.rb でAST生成。
- CRuby+spinel_codegen.rb でCコード生成→bin1。
- bin1でASTからgen2.c生成→bin2。
- bin2でASTからgen3.c生成し、gen2.cとgen3.cが一致すればブートストラップ完了。
ベンチマーク結果
- 74の機能テスト、55の性能ベンチマークを完走。
- miniruby(Ruby 4.1.0dev)比で平均約11.6倍高速。
- 例:
- life(Conway's GoL):86.7倍
- ackermann:74.8倍
- mandelbrot:58.1倍
- fib(再帰):34.2倍
- rbtree(赤黒木):22.6倍
- json_parse:10.1倍
- ao_render(レイトレーサー):8.0倍
サポートされるRuby機能
- クラス・継承・モジュール・Struct・alias・定数・オープンクラス
- 制御構文 :if/elsif/else, unless, case/when, while, until, loop, for..in, break, next, return, catch/throw, safe navigation(&.)
- ブロック・クロージャ :yield, block_given?, &block, proc, lambda, method(:name)
- 例外処理 :begin/rescue/ensure/retry, raise, カスタム例外
- 主要型 :Integer, Float, String(イミュータブル・ミュータブル両対応), Array, Hash, Range, Time, StringIO, File, Regexp, Bigint, Fiber
- タグ付きユニオンによる多態値、Nullable型(T?)で自己参照構造体対応
- グローバル変数 :静的C変数に変換、型不一致はコンパイル時検出
- 文字列操作 :<<でミュータブル昇格、+や補間、tr、ljust/rjust/centerなど標準メソッド全対応
- 正規表現 :組み込みNFAエンジン、=~, $1-$9, match?, gsub, sub, scan, split
- Bigint :mruby-bigint利用、必要時のみ静的リンク
- Fiber :ucontext_tによる協調型コンカレンシー、値受け渡し対応
- メモリ管理 :マーク&スイープGC、サイズ分割フリーリスト、非再帰マーク、スティッキービット
- 値型最適化 :小規模クラスは値型C構造体に昇格しGC不要
- シンボル :sp_sym型、リテラルはコンパイル時インターン、Hashはシンボル専用実装
- I/O :puts, print, printf, p, gets, ARGV, ENV[], File.read/write/open, system(), バッククォート
主な最適化内容
- 型推論駆動の最適化 :
- 値型昇格:小規模イミュータブルクラスはC構造体でスタック配置
- 定数伝播:リテラル定数は直接インライン展開
- ループ長キャッシュ:配列や文字列長をループ前に計算・再利用
- メソッドインライン化:短い非再帰メソッドはstatic inline化
- 文字列連結最適化:複数連結は一括mallocで中間生成抑制
- Bigint自動昇格:自己参照加算/乗算パターンで自動昇格
- 静的シンボルインターン:リテラルto_symはコンパイル時定数参照
- split再利用:ループ内splitは同一配列を再利用しアロケーション削減
- デッドコード除去:未使用関数はリンク時に自動削除
- 型推論ループの早期終了:多くのプログラムで1-2回で収束し高速化
- ASTフィールドパースのバイトウォーク最適化
- 警告ゼロビルド :全テスト・ベンチマークで-Werrorをクリア
アーキテクチャ構成
- spinel :ワンコマンドラッパースクリプト(POSIX shell)
- spinel_parse.c :libprismを直結したCフロントエンド
- spinel_codegen.rb :AST→Cコード生成(約2万行、自己ホスティング可能)
- lib/sp_runtime.h :GCや配列・ハッシュ・文字列等のランタイムライブラリ
- lib/sp_bigint.c :任意精度整数(mruby-bigintベース)
- lib/regexp/ :組み込み正規表現エンジン
- test/ :機能テスト
- benchmark/ :ベンチマーク
- Makefile :ビルド自動化
ビルドと依存性
make deps:libprism取得make:パーサ・ランタイム・ブートストラップコンパイラ構築make test:74機能テスト実行make bench:55ベンチマーク実行make bootstrap:自己ホスティング再構築sudo make install:/usr/localへインストールmake clean:ビルド成果物削除- Prism :Rubyパーサとして利用、libprism(C)またはprism gem(CRuby)対応
- CRuby :初回ブートストラップ時のみ必要
- ランタイム依存性なし :生成バイナリはlibc + libmのみ
制限事項
- eval・instance_eval・class_eval 未対応
- メタプログラミング (send, method_missing, define_method動的生成)未対応
- スレッド・Mutex 未対応(Fiberはサポート)
- エンコーディング :UTF-8/ASCII前提
- ラムダ計算 :深いネストのlambda+[]は非対応
ライセンス
- MIT License 採用
- 詳細は LICENSE ファイル参照