wasmtimeでprocess clockの呼び出しでエラーになってしまう時の対応法
この記事は Recruit Engineers Advent Calendar 2022 の17日目の記事です。
結論
wasi-sdkを利用してコンパイルする際、以下2つのオプションを指定すると、wasmtime実行時に模倣されたprocess clockが利用され、process clock呼び出しエラーを回避することができます。
-D_WASI_EMULATED_PROCESS_CLOCK
-lwasi-emulated-process-clocks
~/wasi-sdk-16.0/bin/clang \
--sysroot=/Users/someuser/wasi-sdk-16.0/share/wasi-sysroot \
-D_WASI_EMULATED_PROCESS_CLOCKS \
-lwasi-emulated-process-clocks \
-O3 \
-I/Users/someuser/wasi-sdk-16.0/share/wasi-sysroot/include \
-I/Users/someuser/wasi-sdk-16.0/share/wasi-sysroot/lib/wasm32-wasi \
-Isimple \
-I. \
-DFLAGS_STR=\""-O3 "\" \
-DITERATIONS=0 \
core_list_join.c \
core_main.c \
core_matrix.c \
core_state.c \
core_util.c \
simple/core_portme.c \
-o ./coremark.wasm
今回の問題を調査した背景
とある事情でWasm Runtimeのいくつかをベンチマークにかけて性能を比較したいモチベーションがありました。
少し調べたところcoremarkというベンチマークツールを見つけたので、これを利用してwasmtimeとwasmerの性能比較をすることにしました。
wasmerは問題なく動作し、以下のような結果が出力されました。
wasmer coremark.wasm
2K performance run parameters for coremark.
CoreMark Size : 666
Total ticks : 2530796112
Total time (secs): 15.415698
Iterations/Sec : 19460.682221
Iterations : 300000
Compiler version : GCCClang 14.0.4 (https://github.com/llvm/llvm-project 29f1039a7285a5c3a9c353d054140bf2556d4c4d)
Compiler flags : -O3
Memory location : STACK
seedcrc : 0xe9f5
[0]crclist : 0xe714
[0]crcmatrix : 0x1fd7
[0]crcstate : 0x8e3a
[0]crcfinal : 0xcc42
Correct operation validated. See README.md for run and reporting rules.
CoreMark 1.0 : 19460.682221 / GCCClang 14.0.4 (https://github.com/llvm/llvm-project 29f1039a7285a5c3a9c353d054140bf2556d4c4d) -O3 / STACK
その他関連
https://zenn.dev/tanakh/articles/wasm-benchmark
しかし、wasmtimeはいつまでも結果が出力されません。
これを動かすためにはどうすれば良いのか?という疑問が今回の調査のキッカケでした。
調べたこと
同様の問題がないか、調査をしたところ以下のissueが見つかりました。
このissueによると
It looks like the module is calling the clock_res_get API with the ProcessCputimeId clock id is not supported right now. In that sense I don’t think that the wasm module is handling the error reported by wasmtime.
There’s also the separate issue, however, of the need to implement this part of the WASI API as well.
wasmtimeでprocess clockの呼び出しはサポートされておらず、エラーになってしまうというものでした。
実際に手元で RUST_LOG=trace
を有効にしてwasmtimeを実行すると同様のエラーに遭遇します。
Caused by:
Badf: Bad file descriptor
TRACE tracing::span::active > <- wiggle abi;
TRACE tracing::span > -- wiggle abi;
TRACE wasi_common::snapshots::preview_1::wasi_snapshot_preview1 > wiggle abi; module="wasi_snapshot_preview1" function="clock_time_get"
TRACE tracing::span::active > -> wiggle abi;
TRACE wasi_common::snapshots::preview_1::wasi_snapshot_preview1 > id=ProcessCputimeId precision=0
TRACE wasi_common::snapshots::preview_1::wasi_snapshot_preview1 > result=Err(process and thread clocks are not supported
更にissueを読み込んでいくと、これを契機に以下のpull requestが作成されました。
この修正が冒頭に紹介したものとなります。
この修正の概要は以下の通りです。
- WASIのスナップショットから
PROCESS_CPUTIME
の実装が省略される - しかしながら、clockなどの機能は便利であるためワークアラウンドとして模倣されたprocess clockを利用できる仕組みを追加する
- 上記、ワークアラウンドを利用する時は必ず
-D_WASI_EMULATED_PROCESS_CLOCK
フラグを有効にする必要がある - 同時に模倣されたprocess clockライブラリを
lwasi-emulated-process-clocks
利用してリンクさせる必要がある
追加された上記オプションを利用して、https://github.com/eembc/coremark をbuildし直したところ無事動作させることができました。
~/wasi-sdk-16.0/bin/clang \
--sysroot=/Users/someuser/wasi-sdk-16.0/share/wasi-sysroot \
-D_WASI_EMULATED_PROCESS_CLOCKS \
-lwasi-emulated-process-clocks \
-O3 \
-I/Users/someuser/wasi-sdk-16.0/share/wasi-sysroot/include \
-I/Users/someuser/wasi-sdk-16.0/share/wasi-sysroot/lib/wasm32-wasi \
-Isimple \
-I. \
-DFLAGS_STR=\""-O3 "\" \
-DITERATIONS=0 \
core_list_join.c \
core_main.c \
core_matrix.c \
core_state.c \
core_util.c \
simple/core_portme.c \
-o ./coremark.wasm
※buildに利用したwasi-sdkはこちらページからダウンロードしました
実行結果は以下の通りです。
2K performance run parameters for coremark.
CoreMark Size : 666
Total ticks : 2302358394
Total time (secs): 15.187260
Iterations/Sec : 19753.398205
Iterations : 300000
Compiler version : GCCClang 14.0.4 (https://github.com/llvm/llvm-project 29f1039a7285a5c3a9c353d054140bf2556d4c4d)
Compiler flags : -O3
Memory location : STACK
seedcrc : 0xe9f5
[0]crclist : 0xe714
[0]crcmatrix : 0x1fd7
[0]crcstate : 0x8e3a
[0]crcfinal : 0xcc42
Correct operation validated. See README.md for run and reporting rules.
CoreMark 1.0 : 19753.398205 / GCCClang 14.0.4 (https://github.com/llvm/llvm-project 29f1039a7285a5c3a9c353d054140bf2556d4c4d) -O3 / STACK
最後に
ベンチマークは実際のワークロードに併せて、その都度計測することが必要です。
今回のベンチマーク結果はそのまま利用せず、都度都度ご自身の業務要件に併せて性能試験を実施いただければと思います。
wasmtime実行に際し、上手く動作をしない場合は今回の例のように、wasi-libcのオプションを見直したり、Rust_LOGオプションを有効化することで解決の糸口が見つかるかもしれません。
この記事が何かしらの一助になれば幸いです。