Wasm Component Model や WASI の概要を調べる
WASMの前提知識がない者が WebAssembly Component Model の概要を知ろうとしたときのメモです。
トピック概観
基盤になっているものから順に:
-
WebAssembly (Core) Specification 2.0
- Wasmのコア仕様(Core Wasm)はかなり低水準なインタフェースしか提供しない。実際のところ各々のWasmを支援するツールチェインがその言語側やブラウザ側などに独自のバインディング用コードをたくさん生成することで成り立っている。Wasmモジュール間の相互運用性は乏しい。
-
WebAssembly Component Model
- Wasmのための標準の高水準インタフェースを定めることで、Wasmの相互運用性などを実現しようとするもの。
- WASI 0.2〜もこの Component Model のインタフェースに従って実現される。
-
WASI 0.1 (Preview 1) → 0.2 (Preview 2)
- WebAssemblyのための標準APIを定めようとするもの(今まではそんなものは何もなかった)。WASI 0.2 は Component Model の仕組みに基づいて実現される。様々なプラットフォームやデバイスでなるべく共通のAPIが使えたらうれしい。
- その他
- 各種ツールチェイン、ライブラリ
- WasmGC(今のところあまり関係ない?)
日本語圏で詳しそうな方:
Core Wasm
ツール
以前からあるツール:
- wabt (wasm/watの操作など): https://github.com/WebAssembly/wabt - The WebAssembly Binary Toolkit
- binaryen (コンパイル・最適化をはじめとして具体的なコードに踏み込むようなツール): https://github.com/WebAssembly/binaryen - Optimizer and compiler/toolchain library for WebAssembly
- など
Bytecode AllianceによるRust製ツール&ライブラリ:
- wasm-tools (Component Modelにも対応。Rustによるwabtのようなもの(?)でありつつ、wasm-toolsのサブクレート群はRustのライブラリとしても使える) https://github.com/bytecodealliance/wasm-tools - CLI and Rust libraries for low-level manipulation of WebAssembly modules
モジュールの構造(概要)
モジュール: https://webassembly.github.io/spec/core/syntax/modules.html
Core specではwasmのルート要素はモジュール。モジュール(テキスト形式)がもつ要素は:
-
type
- 関数の型を定義する -
func
- 関数 -
table
- reftype (funcref, externref) のテーブル。関数の間接呼び出しに使われる。 -
memory
- メモリ -
global
- グローバル変数 (const or mut) -
start
- モジュール初期化後に実行される関数を指定できる -
elem
- テーブルの初期値を設定する -
data
- データセグメント。メモリの指定範囲に初期値を設定する -
export
- func, table, mem, global のエクスポート -
import
- func, table, mem, global のインポート
ちなみに、Wasm Component Model ではルート要素は Module でなく Component になり、まったく違う構造になる。
Wasm - Feature Extensions
Wasm 2.0 の変更点(現時点での): https://webassembly.github.io/spec/core/appendix/changes.html
Wasmの拡張機能のサポート状況:
WebAssembly Component Model
YouTube: Keynote: What is a Component (and Why)? - Luke Wagner, Distinguished Engineer, Fastly
Wasm 同士を組み合わせて使うことは難しかった。Core Wasm自体は非常に低水準なインタフェースしか持っておらず、高水準なインタフェースは標準化されていなかった。Wasm間の相互運用性は非常に乏しい。
そこで、Wasmのうえに高水準な標準インターフェースを定めようとするのが Wasm Component Model。
- https://component-model.bytecodealliance.org/ (user-focussed explanation)
- https://github.com/WebAssembly/component-model
WASI 0.2もこの Component Model に基いて作られる。
WIT = WebAssembly Interface Type (IDL)
WebAssembly Component Model におけるインタフェース定義言語 (IDL)
WITをもとに各言語のBindingsを生成できる。
WITに登場する概念:
- World
- component が従うインタフェースのセットを定める。当該の component のWorldが、対象のWorldに比べて import が過少だったり export が過剰だったりしても、そのWorldには準拠しているとみなせる。
- World は、 Interface を import, export してもいいし、World に 関数宣言を直接置いてもいい
- Interface
- 再利用可能なインタフェースを定める
- Package
- レジストリに公開するときの単位
- その他、データ型の定義など。
Registry
コンポーネントレジストリの仕様 warg が開発されている。
- https://github.com/bytecodealliance/registry
- https://warg.io/
- https://wa.dev/ (wargに準拠したレジストリの実装の一例)
Registry(認証付きのパッケージインデクス)vs Repository
Component Model 周りの開発ツール
Bytecode Alliance が crates.io に登録したライブラリ&ツールの一覧 → https://crates.io/teams/github:bytecodealliance:wasmtime-publish?sort=new
基礎ツール&ライブラリ
- wasm-tools (Rust版のwabtのようなものに加えてComponents周りの機能も持つ) https://github.com/bytecodealliance/wasm-tools - CLI and Rust libraries for low-level manipulation of WebAssembly modules
各言語において
-
Rust:
- cargo component: https://github.com/bytecodealliance/cargo-component
- wit-bindgen (WITからRustを含むいくつかの言語用のbindingを生成): https://github.com/bytecodealliance/wit-bindgen
-
JS / Node.js:
-
https://github.com/bytecodealliance/jco
- component model → Core Wasm へのtranspileもできる。
- https://github.com/bytecodealliance/ComponentizeJS
-
https://github.com/bytecodealliance/jco
-
Python:
-
https://github.com/bytecodealliance/Componentize-py
- wasmtime の component-model 機能にはまだ直接的に対応していない?
-
https://github.com/bytecodealliance/Componentize-py
- など
Warg 関係
-
warg
コマンド: https://crates.io/crates/warg-cli -
wit
コマンド: https://crates.io/crates/wit
WAC (WebAssembly Compositions)
components を合成(どのインポートにどのエクスポートを繋いで...)するための言語。witの拡張:
Component Modelの構成要素 (概要)
-
core module
- Core Specのmodule -
core instance
- インスタンス (とは何?) (core が付いているのは、モジュールを結合する仕組みとしてCore Specに入れたかったためのようだけど...今のところ保留されている模様?)- moduleのインスタンス化または inlineexport の列
-
core type
- Core Specのtype。関数だけでなくモジュールも扱えるように拡張されている。 -
component
- コンポーネントはコンポーネントをもてる(入れ子にできる)。 -
instance
- core:instanceの参照 -
alias
- 他のコンポーネントやモジュールがexportする定義を自コンポーネントに取り込む(?) -
type
- Component Modelの型定義 -
canon
- Core wasmのfuncをCanonical ABIなfuncで包む、あるいはその逆をする。 -
start
- module の start のようなもの。少し異なる点として、引数および戻り値の格納先としてComponentのvalueを使えたり、初期化中の複数時点において実行できたり。 -
import
,export
- インポート・エクスポート- Coreの、モジュール、関数型
- Component Modelの、値、型、関数、コンポーネント、インスタンス
- モジュールと違って、メモリを共有するなどはできない(サンドボックスの強化。WasmGCを使うコンポーネントと従来通りの線形メモリなコンポーネントの連携。など)。
Component Modelの値
値型(コピー渡し)とリソース型(ハンドル渡し)がある。
値型(コピー渡し):
-
bool
,s8
,s16
,s32
,s64
,u8
,u16
,u32
,u64
,f32
,f64
-
char
— Unicode Scalar Value -
record
— 名前付きタプル (特殊形:tuple
,flags
) -
variant
— Tagged Unions (特殊形:enum
,option
,result
) -
list
— シーケンス (特殊形:string
= list char)
リソース型(ハンドル渡し)。リソースの実体は各コンポーネントのインスタンス内にあり、直接触れることはできない。あくまでもハンドルで参照する。
-
own
— 所有しているリソースのハンドル。ドロップ時に解放処理 (dtor) を呼ばなければならない -
borrow
— 借用しているリソースのハンドル。現在のexport callを超えた取り回しをしてはならない。
リソースはコンポーネントインスタンスごとに用意されるハンドルテーブルで管理される。ハンドルテーブルは u32 のハンドル値を u32(たいていはメモリアドレス?)に変換するもの。
関連記事
WASI 0.2
WASI 0.1 (Preview 1。古いWASI) はWASIの初期開発段階。すでに広く使われていて、対応しているランタイムも多い。WASI 0.1 は WITX というIDLを使っていた。WITXは、WebAssembly Text Format のうちimportとexportだけを持つようなもの。WASIリポジトリのlegacyに残っている。
WASI 0.2 (Preview 2) からは、独自のIDLでなく、今後の標準技術となる WebAssembly Component Model に従う。Component Model による標準化の恩恵をそのまま受けられる。言いかえれば、WASIの役割は、Component Modelにおいて「様々なWorldで一般的に使われるインタフェース(ファイルシステム、etc.)を標準化すること」である。
WASI 0.3 (Preview 3) は async まわり (future, stream) のサポートを目指す?など → 0.3 が WASI version 1 として標準化される予定?
wasi.dev
解説サイト https://wasi.dev/ (内容はまだあまりない)
wasi.dev が語る夢:
- 「言語間をつなぐためにHTTPベースのマイクロサービスのような不確かなインタフェースは要らなくなる」
- 「プラグイン機構のあるアプリケーションはみんなWASI使えばいいと信じてる」
- 「複数の言語にSDKを提供するプロジェクトにも適する」
誰のためのもの?
- web app
- plugins
- serverless functions
- user-defined functions in database
- embedded controller
- sidecar networking filters
- etc.
WASIに対応しているランタイム:
Wasmtime, WAMR, WasmEdge, wazero, Wasmer, wasmi, wasm3、など
- WAMR -> IoT, Embedded, Edge, etc.
- Wasmtime -> server-side, non-web embeddings, etc.
WASI 0.2
WASI 0.2 以降の WASI は WebAssembly Component Model に基づく。つまり WASI は WIT (WebAssembly Interface Type) で定められる。WASIの具体的な実装はそれぞれの環境が提供する。
WASI Preview 2 は以下のAPIを含んでいる:
- wasi:io 0.2
- wasi:clocks 0.2
- wasi:random 0.2
- wasi:filesystem 0.2
- wasi:sockets 0.2
- wasi:cli 0.2
- wasi:http 0.2
その他の未成熟なPhaseのAPI一覧: https://github.com/WebAssembly/WASI/blob/main/Proposals.md
API Proposals
提案されているAPIは、 WASI GitHub repository にある。
Wasm Runtime
-
Wasmtime: https://github.com/bytecodealliance/wasmtime (by Bytecode Alliance)
- A fast and secure runtime for WebAssembly
- JIT or AOT なコード生成部分である Cranelift (https://cranelift.dev/) も含む
- Python用ライブラリも: https://github.com/bytecodealliance/wasmtime-py
-
WAMR: https://github.com/bytecodealliance/wasm-micro-runtime (by Bytecode Alliance)
- WebAssembly Micro Runtime (WAMR)
- 資源が限られる組込み/IoTやエッジ向けのランタイム
- WasmEdge: https://wasmedge.org/ (Linux Foundation, CNCF)
-
Wazero: https://wazero.io/
- Go用。依存ライブラリなし。
-
wasmi: https://github.com/wasmi-labs/wasmi
- インタプリタ(あえて)
- etc.
事例
Component Model / WASI
- Plugins:
- VS Codeの拡張機能
- Zed (editor) の拡張: https://github.com/zed-industries/zed/tree/main/crates/extension_api
- Lapce (editor): https://lapce.dev/
- Veloren (game): https://github.com/veloren/veloren/tree/master/plugin
- sqlc のプラグイン:
https://github.com/sqlc-dev/sqlc-gen-typescript/tree/main
- Serverless/FaaS:
その他Wasm
- Microsoft Flight Simulator: https://docs.flightsimulator.com/html/Programming_Tools/WASM/WebAssembly.htm
- Envoy: https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/wasm_filter
- SingleStore, ScyllaDB, etc.: データベースのユーザ定義関数として利用できる
- Shopify Functions: https://shopify.engineering/javascript-in-webassembly-for-shopify-functions
- DuckDB: https://duckdb.org/docs/api/wasm/overview.html
- ブラウザでの利用はもちろん色々ある:
- Figma, Photoshop, AutoCAD, Unity などなど
- Goodnotes: https://web.dev/case-studies/goodnotes#why_use_wasm_and_the_web
トーク
Keynote: What is a Component (and Why)? - Luke Wagner, Distinguished Engineer, Fastly
- a component is an (emerging) standard portable lightweight finely-sandboxed cross-language compositional module.
- components:
- SDKs for free -- "app" と "platform" をつなぐための大量の仕事が要らなくなる。なおかつ任意の言語に対応できる。
- secure polyglot packages -- 異なる言語の部品を自由に組み合わせられる +強力なサンドボックス
- modularity without microservices
- virtual platform layering -- インタフェースによる、低オーバヘッドで強力な分離 → プラットフォームのレイヤ分け
WebAssembly Component Model: What? How? And why you should not ignore it! by Thorsten Hans @ Wasm IO
The next evolution of WebAssembly - the component model
Deconstructing WebAssembly Components by Ryan Levick @ Wasm I/O 2024
Keynote: View from Above: A Birds-eye View of the Wasm Landscape and Where... Bailey Elizabeth Hayes
Wasmコンポーネントモデル、完成間近!WebAssemblyの最新動向についてchikoskiさんに聞いてきた!
Discussion