Upgrade to Pro — share decks privately, control downloads, hide ads and more …

【toranoana.deno#7】Denoからwasmを呼び出す基礎

 【toranoana.deno#7】Denoからwasmを呼び出す基礎

6/22(水)開催のtoranoana.deno#7での発表資料になります。

More Decks by 虎の穴ラボ株式会社

Other Decks in Technology

Transcript

  1. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. denoでwasm呼ぶ基礎
 


    虎の穴ラボ 藤原 佳顕
 1
  2. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. アジェンダ
 •

    概要 • watについて • Denoからのwasmの取り扱いについて • まとめ 2
  3. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. 自己紹介
 3

    • 名前
 ◦ 藤原佳顕
 • 仕事
 ◦ FantiaとかCreatiaとか社内アプリとか
 • 好み
 ◦ Clojure、Rust
 • 趣味
 ◦ 格闘ゲーム
 ▪ Melty Blood、Guilty Gear
 ◦ ダライアス外伝

  4. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. 概要
 4

    • Denoからwasmを呼ぶのをいくつか試してみたので紹介します
 • wasmのコードは以下の本の序盤の内容になります
 ◦ https://www.amazon.co.jp/dp/4798173592/ref=cm_sw_r_tw_dp_ADTSNXQRE1PDMECHT79E
 ◦ wasm自体の書式はwatになります
  5. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. watについて
 5

    • https://developer.mozilla.org/ja/docs/WebAssembly/Understanding_the_text_format
 • 「wasmバイナリーのテキスト表現」
 ◦ 一種のプログラミング言語っぽいもの
 • S式形式と線形命令形式の2パターンある
 ◦ S式は名前の通りLisp系言語で使われるS式
 ◦ 線形命令形式はスタックを直接操作するようなスタイル

  6. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. watについて
 6

    • 線形命令スタイル
 (module (func (export "AddInt") (param $value_1 i32) (param $value_2 i32) (result i32) local.get $value_1 local.get $value_2 i32.add ) )
  7. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. watについて
 7

    • S式スタイル
 (module (func (export "AddInt") (param $value_1 i32) (param $value_2 i32) (result i32) (i32.add (local.get $value_1) (local.get $value_2)) ) )
  8. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. Denoからwasmを扱う
 8

    • 公式ドキュメント通りの方法
 const wasmCode = await Deno.readFile("AddInt.wasm"); const wasmModule = new WebAssembly.Module(wasmCode); const wasmInstance = new WebAssembly.Instance(wasmModule); const value1 = parseInt(Deno.args[0]); const value2 = parseInt(Deno.args[1]); const addInt = wasmInstance.exports.AddInt as (v1: number, v2: number) => number; console.log(addInt(value1, value2).toString());
  9. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. Denoからwasmを扱う
 


    9 • https://deno.land/manual@v1.8.3/getting_started/webassembly 
 ◦ サンプル上はバイナリがハードコーディングされていますが、ファイル読み込みに変更しています 
 • 一方MDNの資料
 ◦ https://developer.mozilla.org/ja/docs/WebAssembly/Loading_and_running 
 ◦ > 新しい WebAssembly.compileStreaming/WebAssembly.instantiateStreaming メソッドは、より効率的 です。
 • => Web APIに準拠しているのであれば使えるのでは? 

  10. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. Denoからwasmを扱う
 


    10 • instantiateStreamingを使うことでファイル読み込みとwasmのインスタンス化が一度に できる
 ◦ MDNのサンプル上はネットワーク経由でのfetch 
 ◦ 今やりたいのはローカルファイルの読み込み 
 ▪ →fetch経由でローカルファイルを読み込めるか 
 • Denoではローカルファイルfetchがサポートされている 
 ◦ https://deno.land/manual/runtime/web_platform_apis#fetching-local-files 

  11. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. Denoからwasmを扱う
 11

    • instantiateStreamingを使う
 const wasmInstance = await WebAssembly.instantiateStreaming( fetch(new URL("./AddInt.wasm", import.meta.url).toString()), {}, ); const value1 = parseInt(Deno.args[0]); const value2 = parseInt(Deno.args[1]); const addInt = wasmInstance.instance.exports.AddInt as (v1: number, v2: number) => number; console.log(addInt(value1, value2).toString());
  12. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. Denoからwasmを扱う
 


    12 • wasmが対応している型
 ◦ i32/i64/f32/f64
 • JavaScriptのNumber型
 ◦ https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Obje cts/Number
 ◦ `JavaScript の Number 型は IEEE 754 の倍精度 64ビットバイナリー形式であり `
 ◦ Numberではi64が表現しきれない 

  13. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. Denoからwasmを扱う
 


    13 • BigInt
 ◦ https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Obje cts/BigInt
 ◦ ES2020で導入された任意精度な整数値 
 • 数値のあとに`n`をつけるか、BigInt関数で作れる 

  14. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. Denoからwasmを扱う
 


    14 • i32だった部分をi64に変更
 (module (func (export "AddIntBig") (param $value_1 i64) (param $value_2 i64) (result i64) local.get $value_1 local.get $value_2 i64.add ) )
  15. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. Denoからwasmを扱う
 


    15 • DenoならそのままBigIntが利用可能 
 const wasmInstance = await WebAssembly.instantiateStreaming( fetch(new URL("./AddIntBig.wasm", import.meta.url).toString()), {}, ); const value1 = BigInt(Deno.args[0] || 0); const value2 = BigInt(Deno.args[1] || 0); const addInt = wasmInstance.instance.exports.AddIntBig as (v1: BigInt, v2: BigInt) => BigInt; console.log(addInt(value1, value2).toString()); $ deno run -A AddIntBig.ts 9007199254740991 9007199254740991 > 18014398509481982
  16. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. まとめ
 •

    DenoがWeb APIを取り込んでいるおかげでwasm関連のものはMDNのドキュメント等を 見ることでほぼそのまま動くことがわかりました 
 • UI関連までwasm側で実装したものがDeno+WebViewとかで動くかは今後やってみたい です
 16