Closed51

Wasm

high-ghigh-g

◯TODO

  • wasm何ができるのかの概要
  • 2022年現在どういった状況にあるのか
  • 環境構築
  • Hello, World
high-ghigh-g

WebAssemblyが生まれた背景は、単純にjsよりももっと早くコードを実行する方法がほしかった為

high-ghigh-g

wasm自体は、webでもアセンブリでもない
wasmの仕様そのものには、特にwebに関するものが入っていない
jsと対比してネイティブな形式に近いだけ

high-ghigh-g

jsの上位互換ではなく、協調して動作させるweb周辺技術の一つ
wasm自体は計算しか出来ない
計算をjsよりも速く実行できる様に設計されている

high-ghigh-g

wasmはプラグインとして使いやすい設計
利用する側からimportするような記述がない限り、wasm自体がTCPコネクションを開いたりといったことがない

high-ghigh-g

wasmはコンパイル先の対象となるバイトコード
バイトコードなので、そもそもコンパイラが必要
GoでもC++でもRustでもよい

high-ghigh-g

wasmで書かれたコードが高速に実行できる必要があるのはもちろんだが、それを利用するために、
wasmのコードのダウンロード、パース、コンパイルに時間がかかっていては意味がない。
パースやコンパイルがしやすいフォーマットでないといけない。

high-ghigh-g

Wasmで書かれたプログラムはどんなCPUでもどんなOSでもwasmのvmがある限りは同じ様に動くことを意図して設計されている。

high-ghigh-g

wasmをブラウザで扱う場合、ブラウザはスクリプトをjsしか解釈しないので、
結局jsで出来ること以上のことはできない

high-ghigh-g

現時点で、メジャーなブラウザはwasmをサポートしている
そのへんのwebサイトを開くだけでもwasmが裏で動いている

high-ghigh-g

3D、動画もwasmに頼れば速く動かせる、google meetのぼかし機能やバーチャル背景もwasm

high-ghigh-g

サーバサイドにwasmを利用するケースも考えられる
wasmでの画像加工など

high-ghigh-g

wasmは、画期的な夢のような技術だと思われるかもしれないが、
Javaが大昔から目指していたものであるし、ブラウザではasm.jsなどもそうだ
既存技術と比べて飛び抜けたものではない。

ただ、高速に動作し、CPUのアーキテクチャやOSでもに非依存、特定のVMでない環境で動作できる、ベンダー比依存などの部分はwasmの大きな強み

high-ghigh-g

JSやTSの代替技術ではない。あくまで共存する技術
なので、信じられないほど爆発的に普及するものでもない

FlutterやBlazorはwasmを利用することができる為、
結果的にこれらのおかげでwasmが普及する可能性はある。

high-ghigh-g

普及することで、これまでは存在しなかった要件がwebに求められることになる
計算がエグい今より何倍もリッチなエフェクトや機械学習など

high-ghigh-g

js/tsとwasmの両方を書き分けられるのがベストだが、
システム案件においては、まだそういったことは必要なさそう

high-ghigh-g

WASM対応フロントエンドフレームワーク
Yew(Rust)
Blazor(MS開発、VueとReactのあいだっぽい感覚)
TeaVM(Java)
Vogu(Go、html+Go的な感覚)

high-ghigh-g

現状は言うまでもなく今後のWasmの発展をもってしても、JavaScriptを過去のものにするようなことはないでしょう

high-ghigh-g

「Reference Types」とは、JavaScriptの参照オブジェクトをそのままWasmの関数に渡したり、Wasmの関数から返したりできるようにする、という仕様

high-ghigh-g

環境

Rustインストール

curl https://sh.rustup.rs -sSf | sh

source入力でターミナル入力でrustupを利用可能にする

source $HOME/.cargo/env

cargoコマンドが利用できるか確認

cargo --version

rustのツールチェインを更新

rustup update
high-ghigh-g

rustのhello worldだけしてみる。

  1. main.rsというファイルを作る
  2. fn main() { println!("hello rust"); } という記述を行う
  3. rustc main.rsで、ビルドファイルを作成(mainという名前のファイルが生成される)
  4. ./mainで実行
high-ghigh-g

cargo new ◯◯ でプロジェクト作成可能
create-react-app的な感覚

cargo newで作成したディレクトリ内は、以下が作成される
Cargo.toml src/main.rs

high-ghigh-g

Cargo.tomlに下記を追記

[lib]
crate-type = ["cdylib"]
high-ghigh-g

lib.rsを下記にする

#[no_mangle]
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}
high-ghigh-g

2つの符号付き32bit整数を和として返す

#[no_mangle] を記載することで、addという関数名のままjs側で実行できるようになる

high-ghigh-g

↓webAssemblyにコンパイル

cargo build --target=wasm32-unknown-unknown --release
high-ghigh-g

index.htmlを作成し、以下を記

      const wasm = './target/wasm32-unknown-unknown/release/wasm_dev_book_hello_wasm.wasm'
      fetch(wasm)
        .then((response) => response.arrayBuffer())
        .then((bytes) => WebAssembly.instantiate(bytes, {}))
        .then((results) => {
          const { add } = results.instance.exports
          console.log(add(1, 2))
        })

wasmファイルをfetch

arrayBufferでバイナリ配列化する

バイナリ配列をWebAssemblyのコードとして、インスタンス化

WebAssemblyインスタンスからadd関数にアクセスして利用

high-ghigh-g

Firefox 58 の新機能として、 WebAssembly モジュールを基礎となるソースから直接コンパイルおよびインスタンス化する機能があります。

これは WebAssembly.compileStreaming() と WebAssembly.instantiateStreaming() メソッドを使用して実現します。

これらのメソッドは、バイトコードを直接 Module/Instance インスタンスに変換することができるので、Response を ArrayBuffer に別途格納する必要がないため、ストリーミングではない対応するメソッドよりも簡単になっています。

high-ghigh-g

var importObject = { imports: { imported_func: arg => console.log(arg) } };

WebAssembly.instantiateStreaming(fetch('simple.wasm'), importObject)
.then(obj => obj.instance.exports.exported_func());

high-ghigh-g

WebAssembly.instantiateStreamingを利用すると、
下記のようにfetch→arrayBuffer→WebAssembly.instantiateをまとめて記述可能

fetch(wasm)
.then((response) => response.arrayBuffer())
.then((bytes) => WebAssembly.instantiate(bytes, imports))

WebAssembly.instantiateStreaming(fetch(wasm), imports).then((results) => {

high-ghigh-g

画像加工をフロントエンド側だけでやるとかか

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