Slide 1

Slide 1 text

Copyright (C) 2021 Toranoana Inc. All Rights Reserved. denoでwasm呼ぶ基礎
 
 虎の穴ラボ 藤原 佳顕
 1

Slide 2

Slide 2 text

Copyright (C) 2021 Toranoana Inc. All Rights Reserved. アジェンダ
 ● 概要 ● watについて ● Denoからのwasmの取り扱いについて ● まとめ 2

Slide 3

Slide 3 text

Copyright (C) 2021 Toranoana Inc. All Rights Reserved. 自己紹介
 3 ● 名前
 ○ 藤原佳顕
 ● 仕事
 ○ FantiaとかCreatiaとか社内アプリとか
 ● 好み
 ○ Clojure、Rust
 ● 趣味
 ○ 格闘ゲーム
 ■ Melty Blood、Guilty Gear
 ○ ダライアス外伝


Slide 4

Slide 4 text

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になります

Slide 5

Slide 5 text

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式
 ○ 線形命令形式はスタックを直接操作するようなスタイル


Slide 6

Slide 6 text

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 ) )

Slide 7

Slide 7 text

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)) ) )

Slide 8

Slide 8 text

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());

Slide 9

Slide 9 text

Copyright (C) 2021 Toranoana Inc. All Rights Reserved. Denoからwasmを扱う
 
 9 ● https://deno.land/[email protected]/getting_started/webassembly 
 ○ サンプル上はバイナリがハードコーディングされていますが、ファイル読み込みに変更しています 
 ● 一方MDNの資料
 ○ https://developer.mozilla.org/ja/docs/WebAssembly/Loading_and_running 
 ○ > 新しい WebAssembly.compileStreaming/WebAssembly.instantiateStreaming メソッドは、より効率的 です。
 ● => Web APIに準拠しているのであれば使えるのでは? 


Slide 10

Slide 10 text

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 


Slide 11

Slide 11 text

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());

Slide 12

Slide 12 text

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が表現しきれない 


Slide 13

Slide 13 text

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関数で作れる 


Slide 14

Slide 14 text

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 ) )

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

Copyright (C) 2021 Toranoana Inc. All Rights Reserved. まとめ
 ● DenoがWeb APIを取り込んでいるおかげでwasm関連のものはMDNのドキュメント等を 見ることでほぼそのまま動くことがわかりました 
 ● UI関連までwasm側で実装したものがDeno+WebViewとかで動くかは今後やってみたい です
 16