RubyKaigi 2022 キーノートレポート

Yuta Saitoさん「RubyはWebAssemblyと出会った」 〜RubyKaigi 2022 1日目キーノート

9月8日から9月10日までの3日間RubyKaigi 2022が三重県津市で開催されました。今年はRubyKaigi 2019以来、3年ぶりの現地開催で非常に盛り上がったカンファレンスとなりました。

初日のキーノートではRubyコミッターのYuta Saitoさんが「Ruby meets WebAssembly」というタイトルで発表しました。

Saitoさんはインターネット上では主に@kateinoigakukunという名前で活動しており、Swiftコミッターとしてもよく知られたエンジニアです。CRubyのWebAssembly移植を進め、2022年1月にRubyコミッターとなっています。今回のキーノートはCRubyのWebAssembly対応でなにができるようになったか、その対応をどのように進めたかという内容でした。

RubyをWebAssembly上で動かす動機

はじめに、RubyをWebAssembly上で動かす動機について話がありました。

Rubyの良さ

Rubyはプログラマが楽しくなるようにデザインされている言語です。Gemのエコシステムもよくできていますし、素早くプログラムを書くこともできます。

Rubyの難しさ

一方でRubyには難しさもあります。ウェブブラウザやモバイルデバイスのような制限された環境ではRubyのインストールはできませんし、Rubyで書いたプログラムをユーザに配布して動かしてもらうのは簡単ではありません。

初心者にとってはインストールも難しいです。Rubyでプログラムを書いてきた人ならばGemのインストール失敗ログを何度も見たことがあるはずです。

Ruby 🤝 WebAssembly

そのRubyの動作環境の問題をどのように解決できるでしょう? その答えの一つがWebAssemblyです。

WebAssemblyはゲームチェンジャーです。WebAssemblyはスタックベースマシンの実行バイナリフォーマットであり、ポータビリティ、言語非依存、バイナリサイズ、ロード効率、サンドボックスによる安全性などを意識して設計されています。

現代ではブラウザはあらゆる環境で動きますし、Rubyをインストールせずブラウザで試せるようになります。CRubyをWebAssemblyに変換したruby.wasmと自分が書いたRubyプログラムを結合することで、ブラウザ上でRubyプログラムが動きます。

ここで壇上のSaitoさんは、ブラウザ内で実際にCRubyのIRBが動作するirb-wasmを用いてライブデモを実施しました。デモはGemをインストールして利用したりと非常に応用的なもので、実際にブラウザ内で自然にRubyが動いていることが伝わるものでした。

WebAssemblyとWASI

ここまではRuby 3.2のWebAssembly対応とはどんなものか、どんなことができるようになったのかを説明しました。ここからはRubyのWebAssembly対応をどう進めたのかの説明に進みます。

WebAssemblyはどのように動くか

WebAssemblyそのものにはファイルシステムも、時刻も、ネットワークも定義されていません。しかしWebAssemblyにはJavaScriptの関数が提供されており、WebAssembly版のCRubyからするとシステムコールの代わりにJavaScriptの関数を利用しています。

そしてWebAssemblyはWebだけのものではありません。サンドボックスによる安全性、アーキテクチャ非依存、多言語対応という特徴は次の領域などでも有用です。

  • サーバレスプラットフォーム
  • プラグインシステム

WASI

WebAssemblyはJavaScriptの上でだけ動くものではありません。WASIはWebAssemblyに提供するシステムコールインタフェースを標準化したものです。WASIによる互換性は様々な環境、言語に対応しています。今回追加されたRubyもまたその一つです。

WASI + VFS = Portable Ruby App

CRuby自体は.wasmバイナリにすることでポータブルなプログラムになりました。しかしRubyで書かれたプログラムも配布する必要がありますし、多くのWebAssembly関連ツールはワンバイナリを要求します。

そこでSaitoさんはインメモリなリードオンリーの仮想ファイルシステムwasi-vfsを作成しました。wasi-vfsはWASI上で動き、WebAssemblyアプリケーションに対しファイルシステムインターフェースを提供します。これによってCRubyを変換した.wasmバイナリと配布Rubyプログラムを結合して、単一のWebAssemblyプログラムとして配布できるようになりました。

Ruby 3.2のWebAssembly/WASIサポート

Ruby 3.2はWebAssembly/WASIをサポートします。ruby.wasmはnpmパッケージとコンパイル済みRuby処理系を提供しており、手軽にRubyのプログラムをWebAssemblyプログラムに変換できるようになっています。

ここではFastlyのCompute@Edgeというエッジコンピューティング環境上でRubyで書かれたWebAssemblyプログラムが動作する様子をデモしました。このデモはサンプルページで実際に動いている様子を確認できます。

CRubyをどのようにWebAssembly/WASI環境に移植したか

当初Saitoさんは「CからWebAssemblyへのコンパイラはあるしCプログラムであるCRubyの移植は簡単なはずだ」と考えていました。しかしCRubyはうちにいくつものドラゴンを抱えていました。

  • 🐲例外
  • 🐲Fiber
  • 🐲保守的GC

例外の実装

CRubyの例外実装はsetjmp/longjmpに依存しています。setjmp/longjmpはスタックポジション、レジスタ、プログラムカウンタの保存と復元を実行します。しかしWebAssemblyのコントロールフローではgoto/call/returnのみしか許可されていません。

例外の実装のためには現在の実行状態の保存と、保存された実行状態への巻き戻しが必要となります。

Fiberの実装

Fiberはコルーチンのようなもので、プログラムの停止と再開が実現できます。Fiberはresume/yield/transferでコンテキストを切り替えます。コンテキストにはRuby VMスタック、マシンスタック、マシンレジスタ、プログラムカウンタが含まれます。

Fiberの実装のためには現在の実行状態の保存と、保存された実行状態の復元が必要となります。

保守的GCの実装

CRubyの保守的GCはマシンレジスタとマシンスタックもスキャンします。WebAssemblyの実行モデルではコールフレーム内のValueスタックや保存されたローカル変数はスキャンできません。

保守的GCの実装のためには現在の実行状態の保存と、保存された実行状態の復元、コールフレームからローカル変数とValueスタックを読めなければいけません。

Asyncifyの活用

Asyncifyはそれらの足りなかったパーツを埋めてくれます。Asyncifyは非同期なJavaScript関数と同期的なC関数のためにAlon Zakaiに設計された、WebAssemblyでも実行可能な低レベルなプログラムの停止と再開の実装方法です。

AsyncifyはWebAssemblyスタックのWebAssemblyレジスタへの書き出し、call命令前後にスキップと巻き戻しのためのコード追加、WebAssemblyレジスタの保存と復元のコード追加により実現されます。

例外、Fiber、保守的GCの実装のために欠けていた次のものはAsyncifyにより埋められました。

  • 現在の実行状態の保存
  • 保存された実行状態の復元
  • ローカル変数とValueスタックのスキャン

こうしてAsyncifyを使うことでCRubyはWebAssemblyの上で動くようになりました。

FAQとRecap

発表の流れで触れられなかったことをいくつか補足しました。

  • スレッド関連APIはWebAssembly/WASIにスレッドAPIが未実装のため未対応
  • C拡張ライブラリは静的リンクする必要がある
  • .wasmバイナリサイズは標準ライブラリも含めるとBrotli圧縮して5.0M程度
  • 実行速度はAsyncifyがオーバーヘッドになっており、mrubyに近い

まとめ

Ruby 3.2で導入されるWebAssembly対応でどんなことができるのか、Rubyが活躍する局面がまた増える夢が広がる発表でした。また、今年新しくRubyコミッターとなったSaitoさんの力強さがよく伝わるキーノートでした。最近CRubyに触れ始めた人がこんな速度でCRubyに大きな影響を与える開発をリードしていることには驚きを禁じえません。

発表内容で触れられた成果物はかなりの完成度で、各所で活用のアイデアが活発に議論されています。正直「WebAssemblyでRubyを動かす」とだけ聞くと、より向いた言語があるのではないかと考える人もいるかもしれません。しかしこの発表を聴いたあとは「WebAssemblyはRubyにとっても非常に重要な環境の一つになりうるのかもしれない」と非常に感銘を受けました。Rubyの未来についてまた一つ楽しみになる、RubyKaigiのオープニングキーノートとしてはとても素晴らしい発表でした。

おすすめ記事

記事・ニュース一覧