2023年3月30日
WebAssemblyに注目
(2022-01-31)by Harshal Sheth
本記事は、原著者の許諾のもとに翻訳・掲載しております。
WebAssemblyは今、転換点にあります。今後数年間で、コンテナ化からプラグインシステムやサーバレス・コンピューティング・プラットフォームに至るまで、IT業界全体でWebAssemblyの導入が増えると筆者は予想しています。この記事では、WebAssemblyとは何か、なぜそれが重要なテクノロジーであるのか、現在はどのような分野で利用されているかを説明します。また、WebAssemblyが大きな影響をもたらす可能性がある用途や、WebAssemblyの将来に関する予測も紹介します。
WebAssemblyとは何か
WebAssembly(Wasm)とは、さまざまなプログラミング言語と多様な実行環境の間に位置する中間層です。30以上の異なるプログラミング言語で書かれたコードを.wasmファイルにコンパイルし、そのファイルをブラウザ、サーバ、あるいは自動車でも実行できます。
「WebAssembly」という名前は誤解を招きます。WebAssemblyは元々、Webでのコードの実行を高速化するために開発されましたが、今ではブラウザ以外のさまざまな環境でも実行できます。さらに、WebAssemblyはアセンブリではなく、アセンブリより若干高水準なバイトコードです。
WebAssemblyの解説とその歴史の説明については、数多くの記事が書かれています。ですから、ここでは優れた入門記事をいくつか紹介するにとどめたいと思います。
- A cartoon intro to WebAssembly - Mozilla Hacks - the Web developer blog
- WebAssembly. Scary name, exciting applications. | Nicky blogs
- How WebAssembly changes software distribution | Max Desiatov
WebAssemblyの長所
WebAssemblyが優れているのは、以下の5つの特徴があるためです。
- ポータブル:Wasmのバイトコードのバイナリ形式は標準化されています。このことは、Wasmを実行可能なあらゆるランタイムがどんなWasmコードでも実行できることを意味します1。これはJavaの「write once, run anywhere」(一度書けばどこでも実行できる)というスローガンと似ています。ブラウザに関しては、95%のユーザのブラウザでWebAssemblyを実行でき、残り5%もwasm2jsコンパイラを利用すれば対応できます。サーバに関しては、WasmtimeやWasmerなどのランタイムがあります。リソースが限られているIoT端末でも、WAMRを利用すればWasmコードを実行可能です2。
- 普遍性:多くのプログラミング言語をWasmにコンパイルできます。Wasmがサポートしている言語には、C、C++、Rustなどのシステム言語だけでなく、Go、Python、Rubyなどのガベージコレクション機能を導入している高水準言語も含まれます3。Wasmにコンパイルできるプログラミング言語の一覧はこちらです。
- “ニアネイティブパフォーマンス”:Wasmは「ニアネイティブパフォーマンス」(ネイティブに近いパフォーマンス)を実現するとよく言われます。実際には、Wasmはほとんどの状況でJavaScriptより高速で、特に演算の負荷が大きいワークロードでその傾向が顕著です。また、Wasmは平均でネイティブコードより1.45~1.55倍遅いものの、ランタイムによって結果は異なります。
- 高速な起動時間:Wasmのコールドスタート時間は、それ自体が一つのカテゴリを構成するほど重要です。サーバ上では、WasmはDockerのコンテナと比べて10~100倍高速なコールドスタート時間を実現できます。これはWasmがすべてのコンテナについて新たなOSプロセスを作成する必要がないためです。ブラウザでは、Wasmのデコードと機械語への変換はJavaScriptのパース、解釈、最適化よりも高速であるため、WasmコードはJavaScriptよりも速く最大のパフォーマンスで実行を開始できます4。
- 安全性:WebAssemblyはWebを念頭に置いていたため、セキュリティを重視して設計されました。Wasmランタイムで実行されるコードは、メモリがサンドボックス化され、機能が制約されています。これはコードが明示的に許可されていることしか実行できないことを意味します5。Wasmコードはサンドボックス化されていますが、システムレベルのインタフェースやハードウェア機能など、下層のシステムへのアクセスも依然として許可されています。
WebAssemblyの便利な利用法
JavaScriptの高速化
Wasmとその前身であるasm.jsが開発された元々の動機は、Web上でのクライアントサイドのコードを高速化することでした。Wasmがこの分野で優れていることを示す事例は数多く存在します。
- 例えば、デザインツールのFigmaの中心的なプログラムはC++で書かれ、WebAssemblyにコンパイルされています。Figmaの開発者は、C++で書かれたプログラムにはパフォーマンスとユーザビリティの面で大きなメリットがあり、それをWebAssemblyにコンパイルすることによって読み込み時間を3分の1に削減し、ダウンロードするファイルの容量を劇的に縮小できると述べています。
- パスワードマネージャの1Passwordでは、Wasmへの転換によって、フォームが多いサイトでの動作が最大で13~39倍高速化しました。また、WasmがJavaScriptよりもパフォーマンスが安定しているという点は、レイテンシの影響を受けやすいアプリケーションにとって重要です6。
プログラミング言語の相互運用性
WebAssemblyはプログラミング言語の境界を簡単に越えることを可能にします。通常、ライブラリとフレームワークは1つの言語のみで書かれているため、完全に書き換えない限り、そのコードを別の言語で利用するのは困難です。WebAssemblyでは、別の言語で書かれたコードの実行を簡単にすることができます。これにより、コードを一から書き直すのではなく再利用することが可能になります。
現在、この機能は主にアプリケーションをWebに移植するために利用されています。以下に例を紹介します。
- Figmaは、一部のグラフィックアルゴリズムについて、Skiaという低水準のC++ライブラリを利用しています。自社でアルゴリズムを開発したり、それをJavaScriptに移植したりはしていません7。
- 筆者のお気に入りのチェスサーバであるlichess.orgは、世界クラスのチェスエンジンであるStockfishをユーザのブラウザで実行しており、サーバサイドでStockfishを実行することによる演算負荷を回避しています。
- Google EarthとAdobe PhotoshopはWasmを利用してC++のコードベースをWebに移植しています。
アプリケーションのWeb移植はWasmを利用するうえで最も簡単な出発点となっており、その傾向は今後も続くと予想されます。しかし、Wasmの相互運用性はブラウザに限られません。Wasmはプラットフォームや端末を越えてコードを実行するのにも利用されています。
- Uno Platformは、単一のアプリケーションを開発し、それをWindows、macOS、iOS、Android、Linux、ブラウザで実行できるUIプラットフォームです。このプラットフォームは、アプリケーションがC#とXAMLで書かれており、かなりWindows中心に設計されているようです。また、レガシーアプリケーションを新たなプラットフォームに移植するために必要な労力を減らすことを目的とした活用例が非常に多いのも特徴です。
- Amazon Prime、Disney+、BBCはいずれも自社の動画配信プラットフォームでWebAssemblyを利用しています。例えば、Amazon Primeでは、新機能を膨大な種類の端末に対応させつつ、問題ないパフォーマンスを維持するためにWebAssemblyが活用されています。
WebAssemblyは、アプリケーションの移植以外にも、サーバサイドでの言語間の橋渡しとしても役立ちます。残念ながら、この用途の活用例はまだ多くありません。なぜなら、OSとの通信に利用されるインタフェース(Web Assembly System Interface、略称WASI)や言語の境界を越えて機能するインタフェース(Wasm Component Model)は依然として開発途上であり、必要な成熟度に達していないためです。
プラグインシステム
ほとんどのアプリケーションは、ある程度の成熟度に達すると、エンドユーザによる拡張性が必要になります。従来のアプリケーションは、設定項目を大量に増やしたり、複雑なドメイン固有言語(DSL)を開発したりしてきましたが、管理がとても面倒になることや、開発者がよく知らない言語での作業を強いられることが常でした。
例を考えてみましょう。NGINXなどのシステムでリクエストのフィルタリング規則を設定するとします。そのためには、システム管理者は、なじみのない独自の設定言語で望ましいロジックを宣言型で実装しなければなりません。NGINXの開発者があらかじめ設定したマッチング演算子やフィルタリング演算子は、普段は役立ちますが、システム管理者が望む挙動を実装するうえで大きな妨げとなることがよくあります。また、利用できるツールが少ないので、問題が生じたときのデバッグはストレスがたまるでしょう。
一部の比較的新しいアプリケーションは異なるアプローチを採用しています。そのアプローチとは、インタフェースの標準的なセットを提供し、Wasmランタイムを組み込んだうえで、必要なカスタムロジックを実装するためのWasmバイナリはエンドユーザに提供させるものです。これにより、エンドユーザにとってはるかに柔軟でなじみのあるインタフェースが実現されます。エンドユーザは、自分が選んだ言語で、複雑なビジネスロジックを自由に実装できます。この機能は、他の言語ではセキュリティ上の懸念により不可能でしたが、Wasmではユーザが提供するコードをランタイムがサンドボックス化することによって実現しています。
現在の活用例を見てみましょう。
- 元々Lyftによって開発され、現在では業界全体で利用されているEnvoyプロキシは、拡張機能をWasmで開発し、ランタイムで動的に読み込むことを可能にしています。Envoyを基に開発されたサービスメッシュのIstioにも同様の機能があります。
- Kafkaの代わりとして使用されているRedpandaでは、ユーザがWasmを利用して、独自のストリーミングデータ変換プログラムを書くことができます。
- Open Policy AgentではWasmを利用してポリシーを定義できます。
- MinecraftサーバのFeatherは、サンドボックス内でのプラグインの実行にWebAssemblyを利用しています。
サンドボックス化機能の組み込み
WebAssemblyを他のアプリケーションに組み込むというアイデアは、プラグインシステム以外にとっても有用です。実際、サードパーティライブラリ全体のサンドボックス化や、ファーストパーティコード向けのセキュリティ層の構築に利用できます。
Firefoxはこの分野で先頭に立っており、スペルチェックや画像のデコードなどに利用するサードパーティライブラリのバグから自らを守っています。Wasmは、「汚染レイヤ」を提供するRLBoxというツールと組み合わせることで、強引なプロセス隔離に頼ることなく、こうしたライブラリの脆弱性からシステムを保護します。Firefoxの場合、Wasmバイナリを最終リリースに搭載してすらいません。Wasmへのコンパイルと別の言語へのトランスパイルというプロセスによって、RLBoxとともに、必要なセキュリティを確保しているのです。
このアプローチは一部の重大な脆弱性の悪用を防止できるかもしれません。攻撃者は通常、複数の脆弱性を組み合わせて利用するため、こうした中間的なセキュリティ層は今後の安全性向上にとても役に立つでしょう。
コンテナ化
Dockerの創業者であるSolomon Hykesは、よく引用されているツイートで、WebAssemblyの重要性を次のように強調しています。
WASMとWASIが2008年に存在していたらDockerを開発する必要はなかった。それくらい重要な存在だ。サーバサイドのWebAssemblyはコンピューティングの未来だ。
Wasmがコンテナ化の未来を示していると考えるのには十分な理由があります。Dockerと比べて、Wasmはコールドスタート時間が10~100倍高速で、メモリの使用量が少なく、機能の制約による優れたセキュリティモデルを採用しています。コンテナではなくWasmモジュールが演算とデプロイの標準的な単位となれば、拡張性とセキュリティは向上するでしょう。
こうした変化は突然起きるものではありません。したがって、Wasmベースのコンテナ化は、完全にDockerを代替するのではなく、既存のオーケストレーションシステムに統合される可能性が高いでしょう。
筆者は今後数年間でこの分野の動きがとても盛んになると予想します。既にいくつかのプロジェクトがいち早く動き始めています。
- Microsoft AzureのDeis LabsはKrustletを開発しました。これは既存のKubernetesクラスタでWasmワークロードを実行する方法の一つです。
- Deis Labsは、Wasmを中心とするPaaS(platform-as-a-service)のHippoもリリースしました。筆者はFermyonがこのテクノロジーの商用化を目指しているのではないかと推測します。
- Cosmonicは、wasmCloudプロジェクトにおいて、分散システム向けにWasmコンテナ化とアクターモデルを結合するプラットフォーム兼オーケストレーション層を構築しています。
- Lunaticプラットフォームもアクターモデルを採用しており、単一のWebAssemblyランタイムプロセス上で複数の軽量なコンテナを実行するための最高のサポート機能を搭載しているとみられます。
- SuborbitalのAtmoもプラットフォーム兼オーケストレーションシステムですが、サーバレスのワークロードに比較的大きな重点を置いています。 ### FaaS/サーバレスプラットフォーム FaaS(function-as-a-service)プラットフォームは、ユーザ提供コードを高速かつ安全に実行する必要があります。サーバレスプラットフォームは、コードを短期間実行するために利用されることが多いため、起動時間が特に重要な指標となります。Wasmは超高速なコールドスタートと幅広い言語のサポートにより、サーバレスのワークロードにとって優れた選択肢となっています8。
Cloudflare WorkersとFastly Compute@Edgeが提供するCDNエッジ・コンピューティング・プラットフォームには既にWebAssemblyの実行機能が搭載されています。Fastlyは、市場の他のサービスよりも起動時間が100倍速いと主張しており、その高速化の理由をWebAssemblyベースのコンパイラとランタイムにあるとしています。NetlifyとVercelもこの分野の製品を開発中です。
主要なクラウドプロバイダが構築したサーバレスプラットフォームも後れを取ってはいません。AWS Lambdaは数カ月前(※訳注:翻訳元の記事は2022年1月31日公開)にWebAssemblyサーバレス関数をローンチしており、GCPとAzureもこれに続くと予想されます。
ブロックチェーン
EthereumやSolanaなどのプラットフォームは、ブロックチェーン上で実行できる「スマートコントラクト」と呼ばれるコードをユーザが書くための仕組みを提供します。Ethereumは完全な独自システムを構築しており、コンパイル済みバイトコードのバイナリ表現であるSolidityという言語や、サンドボックスでコードを実行するためのEthereum Virtual Machineを作成しています。Solanaは一部既存のイノベーションを再利用することを選択しており、LLVMコンパイラインフラを利用して、C、C++やRustのコードをバイナリ形式のBerkeley Packet Filterバイトコードの一種にコンパイルします。しかし、Solanaも依然としてSealevelという独自のランタイムを開発しています。
WebAssemblyはこうしたインフラの大部分を既に提供しています。ユーザは、任意の言語でコードを書き、コンパイラインフラによってWasmバイトコードを作成し、無数の高性能なランタイムを利用できます。
しかし、EthereumとSolanaが既にこうしたインフラを構築しているならば、WebAssemblyはどんな価値を提供できるのでしょうか?実際には、主な付加価値はエコシステム関連にあります。例えば、Ethereumはスマートコントラクトを書くための独自言語を持っていますが、これは他言語で書かれたライブラリや共通関数をすべて活用することはできないという意味です。SolanaはRustエコシステムを利用できるため、その点ではEthereumをわずかに上回っています。WebAssemblyの技術的な課題が克服されれば、現在よりはるかに多くの人がスマートコントラクトを開発し、既に使い慣れたライブラリやツールを利用できるようになるでしょう。
このように考えているのは決して筆者だけではありません。例えば、PolkadotネットワークはランタイムとしてWebAssemblyベースの仮想マシンを使用しています。EOS仮想マシンもWebAssemblyがベースです。CosmWasmは複数のブロックチェーンで機能するスマートコントラクトの構築にWebAssemblyを使用しています。Ethereum Virtual MachineをWebAssemblyの一部のみで代替する「eWASM」という案もありましたが、これは立ち消えになったようです。Wasmerランタイムは、明確にブロックチェーン向けに構築された「シングルパス」コンパイラモードを提供します。一方、WasmEdgeは、Ethereumとの互換性があるスマートコントラクト実行エンジンを搭載していると主張しています。
予測と展望
新たなアプリケーションアーキテクチャ
Dockerが仮想マシンを完全に代替できなかったように、WasmもDockerを完全には代替できません。例えば、仮想マシンがカスタムOSカーネルを実行できるのに対して、Dockerのコンテナでは実行できません。同様に、Wasmのコンテナは、x86の256ビットAVX命令などの一部の特殊なCPU命令を利用できないため9、アプリケーションによってはDockerと同等のパフォーマンスを発揮することが不可能です。
筆者の見解では、DockerではサポートされているがWasmではサポートされていないワークロードの差は、現時点ではDockerと仮想マシンの同様の差よりも大きいと考えられます。しかし、Wasmはまだ発展途上のテクノロジーであるため、対応可能なワークロードの種類は増えていくでしょう。Dockerの台頭はマイクロサービスアーキテクチャの台頭と密接に連動していました。これにより、仮想マシンに適したモノリシックなアプリケーションはDockerのコンテナに適したマイクロサービスに置き換えられていきました。いずれはWebAssembly の独自機能を活用した新たなアプリケーションアーキテクチャが登場するでしょう。
コンウェイの法則によれば、アプリケーションのアーキテクチャは、そのアプリケーションを設計した組織のコミュニケーション構造を反映します。コンピューティングの歴史上すべての新しい「リファレンスアーキテクチャ」は、人と人の間で必要な調整の量を減らしてきました。メインフレームから仮想マシンやDockerのコンテナまで、デプロイ可能なユニットを生産するために必要な人間の数は徐々に減少しています。これは、システムをどんどん小さいコンポーネントに分解し、それらのコンポーネントを構築する作業者が、明確に定義されたインタフェースを参照しながら個別に作業できるようにすることによって実現されました。マイクロサービスがモノリシックなアプリケーションを複数の独立したサービスに分解する一方、WebAssemblyはマイクロサービスをさらに小さいコンポーネントに分解しやすくしています10。
これはどのような結果を生むでしょうか?いくつかの可能性を紹介します。
- アプリケーションを中核的なビジネスロジックと他のシステムとの連携に必要なグルーコードに分割した場合、通常はビジネスロジックが他の部分よりかなり小さくなります。グルーコードのインタフェースを、それが提供する機能の実装から分離すれば、ビジネスロジック中心のアプリケーションを構築し、残りを外部の機能プロバイダに任せることが可能になります。これと、長く蚊帳の外に置かれていたアクターモデルを組み合わせたものがwasmCloudのアプローチの本質です。
- もう一つの可能性は、サーバレスアーキテクチャがマイクロサービスを超える次のステップになるというものです。ほとんどのサービスはステートフルな部分とステートレスな部分に分割でき、ステートレスな部分は任意に拡張可能なサーバレス関数として実行できます。この場合、WebAssemblyは、こうしたサーバレス関数にとって便利で簡単に拡張可能なランタイムとして機能します。
- WebAssemblyはサードパーティの依存関係についての見方を変えるかもしれません。モダンなコードはサードパーティのライブラリに大きく依存しており11、そうした依存関係のほとんどは十分に何度も調査されることがありません。最近のLog4jの脆弱性のようなソフトウェアのサプライチェーンの問題が明らかになるにつれて、人々はサードパーティライブラリのセキュリティを真剣に考えるようになると筆者は予想しています。Firefoxのように、WasmとRLBoxを利用して特定のライブラリを隔離するアプローチはいっそう広まっていくでしょう。パフォーマンス上の制約を克服できれば、同一のWasmランタイム内の機能が制約された別個のコンテナにサードパーティライブラリを隔離することも可能かもしれません12。
ブラウンフィールドへのデプロイ
Wasmはいずれ何らかの形でDockerと相互運用できるようになる必要があります。今後2~3年は、Wasmの主な用途は後方互換性の要件が少ないグリーンフィールド(※訳注)へのデプロイとなるため、相互運用性が絶対に必要というわけではありません。しかし、最終的には、Wasmが(特に法人向け環境で)コンテナ化をめぐる競争に完全に勝利するには、ブラウンフィールド(※訳注)へのデプロイが簡単であることが必要です。 (※訳注:本翻訳は既存の投資用語を参照した表現として解釈します。「グリーンフィールド」既存環境による制約がない、新規開発できる環境。「ブラウンフィールド」既に既存のシステム等が動作している、制約つきの環境。)
考えられる結末の一つは、DockerがWasmランタイムを統合することです。これはあり得そうな話ですが、Wasmは今後、十分に差別化され、完全に別個のツールとして利用することが妥当になると筆者は予想しています。その代わり、DockerとWasmのコンテナはオーケストレーション層で統合されるでしょう。
KubernetesがWasmベースの実行を効果的に統合できるか、あるいは新たなオーケストレーションシステムが登場するかは、あまりはっきりしません。一方では、Kubernetesは現在、オーケストレーションに関して他の追随を許さない王者です。その勢いは驚異的で、Wasmによるコンテナ化の推進派はそれに乗じるのが賢明でしょう。MicrosoftのエンジニアはKubernetesとWasmが統合されるという未来に投資しており、Krustletを開発しています。これはKubernetesでWasmのワークロードを実行できるようにするものです。他方、WasmのコードはDockerのコンテナとは要件が異なるとみられるため、Kubernetesとは相性が良くない可能性があります。例えば、Wasmによるサードパーティライブラリの隔離を採用している場合、コンテナ間の通信のために共有メモリを設定するのが便利ですが、これはKubernetesでは困難でしょう。いずれはこうしたWasmネイティブのオーケストレータが懸け橋となり、Dockerからの移行やDockerとの統合が簡単になるはずです。
筆者はこれからWasmオーケストレータの波が来ることを期待していますが、Kubernetesは十分に定着しているため、すぐに廃れはしないでしょう。
標準化されたサーバレス/エッジフレームワーク
ほとんどのサーバレスプロバイダはルートやラムダ関数を定義するための独自のフレームワークを定めています。例えば、Cloudflareは独自の「cf」という型を定め、コードのスキャフォールディングを設定するためにwranglerというCLIツールを提供しています。Fastlyにはキャッシュとのインタラクションとロギングのための一連の独自インタフェースがあり、AWS Lambdaにも同様の設定が存在します。KubernetesのFissionフレームワークは、さまざまな言語を統合するための独自ライブラリを持っています。一部のプラットフォームは、ユーザにDockerのコンテナを提供させ、プラットフォームが実行のみをすれば良いようにすることで、この問題を回避しようとしています。KnativeとFly.ioはどちらもこのアプローチを採用しています。しかし、これらはコールドスタート時間の影響を軽減するために「ワーカープールを温めておく」問題をユーザに転嫁しなければなりません。
現在は標準化されたサーバレス関数の定義とデプロイ仕様を構築するチャンスがあります。人気のServerless Frameworkは、デプロイの抽象化にはそれなりに役立ちますが、依然としてプロバイダ固有の詳細な部分は関数の実装に委ねられています。こうした詳細部分が抽象化されれば、すぐにマルチクラウドのデプロイは大幅に簡単になり、このフレームワークははるかに強力になるでしょう。いずれはサーバレスにおけるTerraformのような存在になるかもしれません13。
パッケージ管理
あらゆるプログラミング言語には、その言語を取り巻くエコシステムが存在します。ほとんどのモダンな言語は一元的なパッケージレジストリを利用しており、PythonにはPyPI、Node.jsにはnpm、Rustにはcrates.ioがあります。こうしたレジストリやそれに付属するツールとワークフローは、高品質なエコシステムの開発や開発者の作業の効率化にとって重要です。
Wasmの場合、WebAssembly Package Manager(WAPM)がこの需要を満たすはずでした。しかし、実際にはプロジェクトはほとんど休止しているようです。この記事の執筆時点(※訳注:翻訳元の記事は2022年1月31日公開)で、過去2カ月に更新されたパッケージは3つにとどまっています。問題は、パッケージがお互いに依存すると想定されているのに対し、WAPMが相互依存関係のないスタンドアロンのWasmバイナリでしか機能しないことです。開発者にとって他の選択肢はWasmモジュールをnpmに公開することですが、npmは言語をまたぐ相互運用性を促進するものではないため、当然ながらJavaScriptやAssemblyScriptを越えるWasmエコシステムを構築するうえで理想的とは言えません。
問題の原因は、実際にはWAPMやnpmではなく、WebAssembly自体が粗削りな点にあります。
現在、意味のあるWebAssemblyアプリケーションを書き、それがランタイムや言語の境界を越える相互運用性を持つようにするには、多大な労力が求められます。また、基本的でないデータ型(文字列や構造体など)のやり取りにはポインタの演算と低水準なメモリの操作が必要です。
これこそ、まさにWebAssembly Component Modelが解決しようとしている問題です。WasmコンポーネントはWebAssembly Interfaceフォーマットを標準化し、こうしたインタフェースの実装・利用の両方のためのコードジェネレータを提供します。つまり、Wasmでランタイムと言語の壁を乗り越えるのが簡単になるのです。
WebAssemblyには高品質なパッケージマネージャを構築する大きな機会があります。このパッケージマネージャは、Wasmモジュールを他の言語から利用するためのバインディングを生成するのにWasmコンポーネントのcodegenを利用すべきでしょう。このツールが十分に優れていれば、言語をまたぐ開発がとても簡単になり、サーバサイドのWebAssemblyエコシステムの可能性を本当の意味で広げる可能性があります。Wasmパッケージレジストリは、他のパッケージレジストリと連携し、適切に生成されたバインディングとともにパッケージをPyPI、npm、crates.ioに自動的に公開することもできるかもしれません。
終わりに
ここまで読んできた方は、「WebAssemblyがそんなに優れているなら、なぜ広く使われていないのか?」と考えていることでしょう。その理由をいくつか挙げたいと思います。
- WebAssemblyはマーケティングがうまくありません。WebAssemblyはWeb限定でもアセンブリでもなく、名前が実体とかけ離れています。WebAssemblyは主にWeb開発者向けにマーケティングと宣伝が行われていますが、実際のポテンシャルはブラウザを越えたところにあります。本当の力が明らかになるのは、C++とRustの開発者がWasmの持つポテンシャルに一斉に気づき始めたときでしょう。
- WebAssemblyは依然として標準化されていません。例えば、WebAssembly System Interfaceには正式に標準化されていない無数の拡張機能がありますが、さまざまなランタイムがこうした拡張機能の一部を実装しています。ユニバーサルポータビリティという目標も完全には実現されていません。
- 言語間のインタラクション機能が不便です。ユーザが実際にさまざまな言語でWasmを使用し始めるには、クリティカルマスに相当する数の言語について、WebAssemblyコンポーネントと優れたコードジェネレータが必要です。
- 開発者体験に大きな改善の余地があります。デバッグをはじめとするツールや、パッケージマネージャ、ビルドシステム、IDEとの統合性が改善されることが理想です。
- こういうことは言いたくないのですが、WebAssemblyのライブラリ隔離機能が正当に評価されるには、Log4Shellと同様の規模の深刻なソフトウェア・サプライチェーン・インシデントがあと何回か起きる必要があるでしょう。
WebAssemblyは名だたる数々のサービスで導入されており、さまざまな用途に利用できますが、IT業界全体では一部で散発的に使われているにすぎません。筆者の友人の中でWebAssemblyを知っている数少ない人たちは、基本的にはWebAssemblyをとても面白いと考えているものの、まだ十分に成熟していないため開発には利用していません。しかし、こうした課題の多くに対して積極的な取り組みが行われており、今後1~2年で問題ない状態に達するでしょう。ですから、私たちは現在、WebAssemblyの利用、エコシステム、コミュニティが爆発的に拡大する瀬戸際にあると思われます。
Hacker Newsでの議論にぜひご参加ください。また、筆者へのご意見も歓迎します。この記事の初期の草案に対するフィードバックをくれたNihar Sheth、Mohak Jain、Andrew Sun、Michelle Fangに感謝します。
注記
- 実際には若干微妙な部分があります。WasmにはWeb APIとWebAssembly System Interface(WASI)APIという2つの標準的なAPIが存在します。また、WebAssemblyは急速に進化しているため、例えばスレッディングのように、広く実装されているが正式には標準化されていない実験的機能が数多くあります。それ以外にも、Wasmが別のアプリケーションに組み込まれる場合、そのアプリケーションが独自のAPIを提供するかもしれません。したがって、Wasmコードが実行されるのは、そのランタイムが対応しているAPIと機能のみを使用する場合に限られますが、これは十分に妥当な想定と言えます。↩
- なぜかは分かりませんが、WebAssemblyのランタイムの名前はすべて「wa」で始まるようです。他にもWasmEdge、WAVM、wasm3があります。数少ない例外の一つがFizzyですが、このプロジェクトもwasmxという組織によってホストされています。↩
- ただし、PythonやRubyなどのインタプリタ型言語やGoなどのランタイムが複雑な言語は、Wasmで実行しても良いパフォーマンスを生まないでしょう。↩
- Firefoxでは、Wasmへのコンパイルはネットワークによるパケットの送信よりも実際に速くなります。WebAssembly.instantiateStreamingメソッドにより、ファイルのダウンロード完了前からコンパイルのプロセスを開始できるため、Wasmコードの実行開始前のレイテンシはごくわずかしか増加しません。↩
- ただし、それでも小さな欠点は残っています。機能ベースの許可システムは依然として粒度が非常に高いわけではなく、ほとんどのWasmランタイムはSpectreのようなサイドチャネル攻撃を防止できないため、追加的な戦略が必要になります。CloudflareのKenton Vardaは、自社の脅威モデルと、脅威を軽減するために実装した対策について、詳細な記事を執筆しています。↩
- WasmはJavaScriptの「ファストパス」から逸脱した場合に生じる脱最適化の問題を回避できるため、JavaScriptの最高のパフォーマンスと同等以上のパフォーマンスで安定して高速にコードを実行できます。面白いことに、実はJavaScriptをWebAssemblyにコンパイルして元のコードの代わりに実行するだけで、ブラウザでJavaScriptの実行を高速化することが可能です。Lin Clarkはその方法とそれがうまくいく理由について、素晴らしい講演を実施しています。↩
- 数年前にFigmaの技術リーダーとの個人的な会話で聞いた情報です。Google ChromeやFirefoxなどの多くのブラウザは既に内部でSkiaを利用しています。しかし、こうしたブラウザはSkia APIを直接は公開していないため、アプリケーションは低速なブラウザDOMやSVGインタフェースを利用しなければなりません。Figmaはこうした低速なレイヤを回避し、ブラウザのキャンバス要素に直接描画しますが、依然としてアプリケーションへの組み込みを通じてSkiaの一部の機能を利用しています。↩
- 他にも注目すべき選択肢があります。例えば、AWS Lambdaは軽量なFirecracker microVMを利用しています。両者を直接比較すると、WebAssemblyのパフォーマンスの方が少し優れています。↩
- WebAssemblyによる128ビット型のSIMDのサポートは、現在は実験的な段階にありますが、多くのブラウザとランタイムに実装されています。「ロングSIMD」のサポートは引き続き今後の課題と言えます。↩
- この主張に対する反論は、「マイクロサービスを分解できるからといって、実際に分解するとは限らない」というものです。これは確かにもっともな批判であり、実はモノリスとマイクロサービスの関係にも当てはまります。例えば、「マイクロサービスを本番環境で始めるべきではない――モノリスは君の友人だ」という最近の記事は大きな議論を呼びました。それでも、マイクロサービスアーキテクチャは、適切な状況で導入すればとてつもなく有効で、生産性を大幅に高めます。筆者はWebAssembly中心のアーキテクチャにも同じことが言えると予想しています。ただし、WebAssemblyに適した状況がどれだけ存在するかはあまりはっきりしません。↩
- この問題はとても有名で、これに関するミームが存在するほどです。↩
- 誰かがこうしたサービスを提供する企業を設立すべきでしょう。最近Log4jの脆弱性が判明したことで、ソフトウェアのサプライチェーンは現在、最も重要な問題となっています。さらに、ほとんどの既存企業は依存関係の隔離よりも検証に重点を置いているようです。↩
- これは最適な比較対象ではないかもしれません。なぜなら、Terraformがデプロイやクラウドプロバイダとのインタラクションのみを抽象化するのに対し、このフレームワークはコード層でも機能するからです。↩
株式会社リクルート プロダクト統括本部 プロダクト開発統括室 グループマネジャー 株式会社ニジボックス デベロップメント室 室長 Node.js 日本ユーザーグループ代表
- Twitter: @yosuke_furukawa
- Github: yosuke-furukawa