👩‍💻

ブラウザの外でのWebAssemblyについての探索

2023/12/10に公開

以前 WebAssembly の利用シナリオを調べるという記事を公開しました。公開して3年経過しておりますが、当時の私の想像よりも WebAssembly は利用ケースは生まれていないというのが正直な感想です。しかし、北米企業においては活用事例が生まれているのではないかという疑問をいだいたため、探してみることにしました。

本稿はこれら探したものについてまとめ、利用ケースを考えるものです。

ブラウザの外のWebAssembly

WebAssembly (以降wasmと示します)は元々、ブラウザ内でコードを高速に実行するために作り出された技術ですが、ブラウザを飛び越えた環境でも利用が検討されています。
wasmの特徴はバイナリ形式のため高速に実行できる点、Wasmバイナリは、高効率な圧縮アルゴリズムにより小さくサイズが保たれる点、サンドボックス化された環境で実行できるためセキュアな点が特徴です。

また、WebAssembly System Interface(WASI)と呼ばれる、wasmがOSにアクセスするためのAPIを定義が策定されています。これを用いることで、様々な実行環境でwasmバイナリが同じように動作することを保証されます。これによってさまざまな環境で実行できるポータビリティーを持っています。
加えて、wasm にしてしまえば、言語を超えた、相互運用性(interoperability)が実現できます。例えば、異なるプログラミング言語(C、C++、Rust、JavaScriptなど)で書かれたコードを共通のバイナリ形式にコンパイルすることができ、これによって異なる言語間での相互運用性を実現できます。

WASIに対応したランタイムで力が入っているものとしては wasmtimeがあります、また、Node.js や Go といった言語のランタイムでも WASI に対応しており、wasmを実行することができます。

node.js の場合

'use strict';
const fs = require('fs');
const { WASI } = require('wasi');
const wasi = new WASI();
const importObject = { wasi_unstable: wasi.wasiImport };

(async () => {
  const wasm = await WebAssembly.compile(fs.readFileSync('./demo.wasm'));
  const instance = await WebAssembly.instantiate(wasm, importObject);
  wasi.start(instance);
})();

Go で実行する場合は、JSのグルーコードなどが必要で単純に.wasm を直接実行することはまだできないようです。セットアップをすれば go:wasmimport というコメントでwasmの関数の実行が可能です。

package main

import "fmt"

//go:wasmimport env helloworld
func helloworld(n int32) int32

func main() {
    fmt.Println(helloworld(10))
}

上記のサンプルから wasm があらゆるランタイムで実行できるイメージが持てると思います。
wasmの特徴に軽く触れたところで事例を見ていきます。

事例

BBC

Building a WebAssembly Runtime for BBC iPlayer and enhanced audience experiences.

BBC R&DではOBMという没入感、インタラクティブ性、パーソナライズされた体験を提供するための技術で、様々なデバイスで利用可能な普遍的なアクセスを目指しているそうです。

WebAssemblyはセキュリティが高く、予測可能な性能を持ち、ブラウザ内外で使用できる点に注目し、適応したとのことです。

具体的には、C++で記述されたメディアアプリケーションをWebAssemblyにコンパイルし、一つのコードベースから多くのプラットフォームで実行できるようにするアプリケーションを開発しました。

ウィンドウやレンダリング、ユーザー入力、メディアのエンコードなどの機能をWebAssemblyモジュールから利用できるようにして Linux、MacOS、Windows、Raspberry Pi、Android などのクライアントでの、実行を実現しているとか。

ランタイムは wasmtime を利用しているとのことです。それぞれの言語やプラットフォームでこのようなプレイヤーアプリを実装するのは結構骨が折れますから、体験を統一させたいこのようなケースにおいては理にかなっていたとのことでしょうか。

InfinyOn

InfinyOn はストーリーミングデータの加工などを行っていたシステムFluvioをRustで開発し、
Wasmtimeで実行することで、Kafka などの Java ベースのプラットフォームと比較して、エンドツーエンドのストリーム処理で5倍を超えるスループットの向上を実現し他とのことでした。
製品の宣伝なので、やや誇張もあるかもしれませんが、Rust実行環境としてのwasmtimeを利用しているとのことです。

Microsoft

Azure では Kubernetes Service の WebAssembly System Interface (WASI) ノード プールのプレビュー版として Wasmtime を提供しているとのことです。

Shopify

Shopify には Shopify Functions というユーザーのバックエンド実行環境を提供しているとのことですが、この実行環境としてユーザーに提供しているとのことです。
小さいモジュールサイズである点はセキュアなサンドボックス環境を提供できるwasmを採用していて、RustやJSなどの複数言語をサポートしているとのことです。こうした企業やシステムが提供するプラグイン言語としてwasmは可能性があるかもしれません。

まとめ

事例を調べていて、BBC の例が気合が入っていて興味深かったです。wasm の利用ケースは確実に増えていますし、ランタイムとしてのwasmtimeも1.0になったことで、採用する企業も増えているようでした。
個人的には、マイクロサービスにおいてwasmで社内のライブラリを共通化、コードのシェアが簡単にできて言語を超えた資産を活用できる!!という事例があるかなと思ったのですが、そのようなものはありませんでした。そもそも言語を超えた、コードベースの共通化などのニーズはないのかもしれません。BBCのように制御できないユーザー側のクライアントに関して同じコードベースを実行するケースや、shopifyのようにプラグイン言語のランタイムとして提供するというユースケースは、定番になっていくかもしれないと感じました。

参考リンク

Discussion