Closed6

WebAssemblyランタイム比較(Lucet, Wasmer, Wasmtime)

ピン留めされたアイテム
Shingo YamazakiShingo Yamazaki

モチベーション

サーバーサイド WebAssembly の文脈で見かけるランタイムとして Lucet, Wasmer, Wasmtime などがあるが、違いがよくわからないので調べたい。

調査すること

以下の Wasm ランタイムを一通りドキュメント読んだりチュートリアルを試す。

参考リンク

全体

Lucet

Wasmer

Wasmtime

Shingo YamazakiShingo Yamazaki

Lucet

開発元

Fastly

インストール手順

Announcing Lucet: Fastly’s native WebAssembly compiler and runtime | Fastly
ここに書いてる手順は若干古い?最新のドキュメントは
Overview - Lucet

特徴

セットアップ手順

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 で書くには...
Shingo YamazakiShingo Yamazaki

🚨 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

https://docs.rs/lucet-runtime/0.6.1/lucet_runtime/
https://docs.rs/lucet-wasi/0.6.1/lucet_wasi/

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
Shingo YamazakiShingo Yamazaki

おおー、Lucetいつの間にか End of Life になってたんですね!
情報ありがとうございます!

Shingo YamazakiShingo Yamazaki

Wasmer

開発元

Wasmer社 https://wasmer.io/

インストール

Getting Started - Wasmer Docs

$ curl https://get.wasmer.io -sSfL | sh

CLI

CLI Usage - Wasmer Docs

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

Wasmer Features - Wasmer Docs

  • Compilers: 複数のコンパイラをサポート
  • Caching
  • Metering 計算時間やその他の資源はモニタリングでき、コントロールできる
  • WebAssembly Features:
    • Bulk-memory operations
    • Multi-value return
    • ...
  • ABIs
    • Emscripten
    • WASI

Language Integrations

Rust - Wasmer Docs

Lucet と同様、Rust プログラムから使うためのライブラリも提供されてそう。

その他

Examples
が充実してたり、Lucet に比べドキュメントはしっかりしてる印象。

TODO

このスクラップは2022/09/06にクローズされました