WebAssemblyランタイム比較(Lucet, Wasmer, Wasmtime)
モチベーション
サーバーサイド WebAssembly の文脈で見かけるランタイムとして Lucet, Wasmer, Wasmtime などがあるが、違いがよくわからないので調べたい。
調査すること
以下の Wasm ランタイムを一通りドキュメント読んだりチュートリアルを試す。
-
Lucet (https://github.com/bytecodealliance/lucet)→ End-of-life。Wasmtime に一本化 - Wasmer (https://github.com/wasmerio/wasmer)
- Wasmtime (https://github.com/bytecodealliance/wasmtime)
- WasmEdge (https://github.com/WasmEdge/WasmEdge)
参考リンク
全体
Lucet
Wasmer
- スタンドアロンなWebAssemblyランタイム「Wasmer 2.0」正式リリース、Win/Mac/Linux対応。SIMDに対応、実行速度が約50%改善、参照型対応など - Publickey
- WebAssemblyをWin/Mac/Linuxで実行可能なランタイム「Wasmer 1.0」正式リリース。事前コンパイルによる高速起動やクロスコンパイルなどにも対応 - Publickey
- WebAssemblyをブラウザの外で動かすWasmerを触ってみた
- Wasmer、WebAssemblyをサーバーサイドに - CIOニュース:CIO Magazine
Wasmtime
Lucet
開発元
Fastly
インストール手順
Announcing Lucet: Fastly’s native WebAssembly compiler and runtime | Fastly
ここに書いてる手順は若干古い?最新のドキュメントは
Overview - Lucet
特徴
-
Using the Lucet runtime API from Rust - Lucet
- Rust から使うランタイムのAPIも提供されてるらしい
セットアップ手順
Lucet で実行可能な Wasm を Rust で書くには
target に wasm32-wasi
を指定する。
$ rustup target add wasm32-wasi
$ cargo build --target wasm32-wasi
Rust のファイルはこんな感じ。
#[no_mangle]
pub fn add(a: i32, b: i32) -> i32 {
println!("{}", a + b);
return a + b;
}
#[no_mangle]
pub fn hello() {
println!("hello");
}
fn main() {
println!("Hello, world from Rust!")
}
lucet-runtime 側は
fn main() {
// rocket::ignite().mount("/", routes![index, execute, upload]).launch();
// ensure the WASI symbols are exported from the final executable
lucet_wasi::export_wasi_funcs();
// load the compiled Lucet module
let dl_module = DlModule::load("guest.so").unwrap();
// create a new memory region with default limits on heap and stack size
let region = MmapRegion::create(
1,
&Limits::default().with_heap_memory_size(10 * 16 * 64 * 1024), // (1)
)
.unwrap();
// instantiate the module in the memory region
let mut instance = region.new_instance(dl_module).unwrap();
// prepare the WASI context, inheriting stdio handles from the host executable
let wasi_ctx = WasiCtxBuilder::new().inherit_stdio().build().unwrap();
instance.insert_embed_ctx(wasi_ctx);
// run the WASI main function
// instance.run("main", &[]).unwrap();
let retval = instance
.run("add", &[5i32.into(), 3i32.into()]) // (2)
.unwrap()
.unwrap_returned();
println!("{}", i32::from(retval)); // (3)
}
(1) with_heap_memory_size()
を指定しないと以下のエラーが出たので指定している
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: LimitsExceeded("heap spec initial size: HeapSpec { reserved_size: 4194304, guard_size: 4194304, initial_size: 1114112, max_size: None }")'
(2), (3) 引数および戻り値の型は
lucet_runtime - Rust
を読む限り明示的に指定する必要がありそう。
未解決
- ✅
Lucet で実行可能な Wasm を Rust で書くには...
🚨 lucet-runtime が Lucet リポジトリ内じゃないと動かない
やりたいこと
Using the Lucet runtime API from Rust - Lucet
- これのとおりに lucet-runtime を動かしたい
- そのために
cargo new
で独立したプロジェクトを作る - サンプルは相対パス指定になっているのでバージョンを指定する
試したこと
1)2021-04-26 時点で lucet-runtime および lucet-wasi の最新バージョンは 0.6.1
Cargo.toml でこのバージョンを指定すると以下のエラー
[dependencies]
lucet-runtime = "0.6.1"
lucet-wasi = "0.6.1"
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: DlError(Custom { kind: Other, error: "dlopen(/Users/yamazaki/repos/github.com/zaki-yama-labs/lucet-playground/lucet-runtime-example/example.so, 2): Symbol not found: _hostcall_wasi_snapshot_preview1_fd_close\n Referenced from: /Users/yamazaki/repos/github.com/zaki-yama-labs/lucet-playground/lucet-runtime-example/example.so\n Expected in: flat namespace\n in /Users/yamazaki/repos/github.com/zaki-yama-labs/lucet-playground/lucet-runtime-example/example.so" })', src/main.rs:8:50
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
2)リポジトリの最新のコミットで試す
[dependencies]
lucet-runtime = { git = "https://github.com/bytecodealliance/lucet", branch = "main" }
lucet-wasi = { git = "https://github.com/bytecodealliance/lucet", branch = "main" }
結果は別のエラー
error[E0599]: the method `set_times` exists for struct `cap_std::fs::File`, but its trait bounds were not satisfied
--> /Users/yamazaki/.cargo/git/checkouts/lucet-d29c7ec0f6d2e0d4/51fb1ed/wasmtime/crates/wasi-common/cap-std-sync/src/file.rs:84:14
|
84 | .set_times(convert_systimespec(atime), convert_systimespec(mtime))?;
| ^^^^^^^^^ method cannot be called on `cap_std::fs::File` due to unsatisfied trait bounds
|
::: /Users/yamazaki/.cargo/registry/src/github.com-1ecc6299db9ec823/cap-std-0.13.9/src/fs/file.rs:32:1
|
32 | pub struct File {
| ---------------
| |
| doesn't satisfy `_: unsafe_io::unsafe_handle::AsUnsafeFile`
| doesn't satisfy `cap_std::fs::File: SetTimes`
|
= note: the following trait bounds were not satisfied:
`cap_std::fs::File: unsafe_io::unsafe_handle::AsUnsafeFile`
which is required by `cap_std::fs::File: SetTimes`
= help: items from traits can only be used if the trait is in scope
= note: the following trait is implemented but not in scope; perhaps add a `use` for it:
`use fs_set_times::set_times::SetTimes;`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0599`.
error: could not compile `wasi-cap-std-sync`
To learn more, run the command again with --verbose.
warning: build failed, waiting for other jobs to finish...
error: build failed
参考にさせていただきました。ありがとうございます。
Lucetはwasmtimeに一本化されていたので貼っておきますね。
おおー、Lucetいつの間にか End of Life になってたんですね!
情報ありがとうございます!
Wasmer
開発元
Wasmer社 https://wasmer.io/
インストール
$ curl https://get.wasmer.io -sSfL | sh
CLI
fn main() {
println!("Hello, world!");
}
$ cargo build --target wasm32-wasi
$ wasmer target/wasm32-wasi/debug/wasmer-playground.wasm
Hello, world!
単純にwasmファイルを実行する以外にもさまざまなサブコマンドがありそう。
To do this, you want to find a Wasm Module compiled down to an ABI that the Wasmer runtime supports, such as WASI or Emscripten. For instance, we can search for a module on WAPM, and go to the module page, and then click on the "Browse modules" tab.
ABIとはApplication Binary Interfaceの略(のはず)。
Features
- Compilers: 複数のコンパイラをサポート
- Caching
- Metering 計算時間やその他の資源はモニタリングでき、コントロールできる
- WebAssembly Features:
- Bulk-memory operations
- Multi-value return
- ...
- ABIs
- Emscripten
- WASI
Language Integrations
Lucet と同様、Rust プログラムから使うためのライブラリも提供されてそう。
その他
Examples
が充実してたり、Lucet に比べドキュメントはしっかりしてる印象。
TODO
- Examples 一通り見る
- https://docs.rs/wasmer/1.0.2/wasmer/ 読む