2020/07/22

WASI 試してみた

WRITER: t.mutaguchi

はじめに

今回のエントリーではずっと気になっていた WASI をようやく試したので、その内容を記載します。

WASI とは?

WebAssembly System Interface の略です。

ブラウザ上でネイティブ並みの実行速度が出せる WebAssembly (WASM)。これをブラウザ以外の用途でも活用できないかと考えた人達がいました。しかし、その場合はホストマシン OS が管理するリソースへのアクセス手段が必要…。このシステムとのインターフェースを仕様として標準化しようという試みが WASI です。Mozilla や Fastly が主だって取り組まれています。

WASI について Docker の共同設立者である Solomon Hykes 氏は以下のようなツイートをされています。

『2008 年に WASM + WASI が存在した場合、Docker を作成する必要はありませんでした。それがどれほど重要な事か。サーバー上の WebAssembly はコンピューティングの未来です。標準化されたシステムインターフェースはミッシングリンクでした。WASI が任務を果たすことを願っています!』

Fastly が 2019/11 に WebAssembly を用いたサーバーレス基盤である Compute@Edge のプライベート・ベータ版をローンチしていたり、2019/12 に W3C が WebAssembly のコア仕様をインターネット標準として勧告していたりと、WASM+WASI 界隈は盛り上がりを見せていて非常に楽しそうです。

Let’s WASI

今回は Lucet (ルーセット) を試してみます。Fastly が開発を進める Lucet は、WebAssembly 用のコンパイラを含むツールチェイン、及び、ランタイムを提供していて、その中に WASI サポートも含まれています。

まずは環境を整える

以下に沿って進めます。
https://github.com/bytecodealliance/lucet/wiki/Getting-started
※ Mac OS X 環境、Docker Desktop はインストール済み

Git クローン & リポジトリルートへ移動 & サブモジュール更新

環境変数の設定

初回実行時はセットアップも行われるため 30 分くらい掛かります。

動作確認

Hello World を試す

以下に沿って進めます。
https://github.com/bytecodealliance/lucet/wiki/Your-first-Lucet-application

作業用ディレクトリ作成 & 移動

hello.c ファイル作成

C ファイル → WebAssembly バイナリ

WebAssembly バイナリ → x86-64 ネイティブコード

Lucet は事前コンパイル形式のため、前もって共有ライブラリを生成します。

Lucet で実行可能か確認

この Hello World では、WebAssembly バイナリを Lucet コンパイラでネイティブコードに変換、実際に動作させるところまでを確認できました。ちなみにホストマシン側の lucet-wasi はコンテナにセットアップされたアプリケーションを実行しているようです。

ランタイムを試す

Rust 製サーバーに Lucet ランタイムを組み込んで WASM 製共有ライブラリの呼び出しを行ってみようと思います。Lucet の開発環境用コンテナには Rust がインストールされているので同じコンテナを使い回しますが、Mac OS X でも Rust 使いたいので Rust 日本語ドキュメントの Getting started を参考にインストールしておきます (インストール作業は割愛)。

リポジトリルートの Cargo.toml を編集

簡易 HTTP サーバー用にバイナリ・アプリケーションとして追加

simple-httpd ディレクトリ、及び、Rust アプリケーションのテンプレートが作成されます。

ディレクトリ移動

src/main.rs を編集

こちらの記事を参考 (ほぼそのまま。。。) にさせていただきました。

サーバー起動 (シェル A で実行)

確認 (シェル B で実行)

問題なくアクセスできましたので、次はランタイムを組み込んでいきます。

lib.c 作成

C ファイル → WebAssembly バイナリ

ライブラリとして使用する前提のオプションを指定しています。

WebAssembly バイナリ → x86-64 ネイティブコード

Cargo.toml を編集

依存するクレートとして lucet-runtime と lucet-wasi を追加します。

src/main.rs を編集

リポジトリルートへ移動

ここからはコンテナ内で作業を行います。

サーバー起動 (シェル A で実行)

確認 (シェル B で実行)

Rust から 1, 2 という数値を共有ライブラリに渡した上で計算を行い、結果として 3 が返ってきているのが確認できました。

まとめ

WebAssembly バイナリは様々な言語から生成できるので、うまく活用できれば言語非依存で実行速度も担保したサービスを提供する事ができそうです。AWS Lambda や Google Cloud Functions を始めとするサーバレス基盤では対応言語に制限がありますが、Fastly Compute@Edge では WASM さえ出力できる言語であればサーバレス基盤の採用が可能になるという事になりますので、Fastly が力を入れるのも頷けます。

ゲームやウェブサービスにおいても、端末側とサーバー側が異なる言語であれライブラリの共有が可能になりますので、アイデア次第ではありますが色々な用途が考えられるのでは無いでしょうか?

参考

t.mutaguchi

t.mutaguchi

バックエンドのアプリケーションエンジニア。
Adobe Flash が廃れた際、フロントエンドからバックエンドに転向した。人生一生勉強。