WebAssembly をざっくり紹介


はじめに

この資料は社内LTイベント用の資料です


WebAssembly (WASM) とは?

Wikipediaより

WebAssemblyは、ウェブブラウザのクライアントサイドスクリプトとして動作するプログラミング言語(低水準言語)である。wasmとも称されており、ブラウザ上でバイナリフォーマットの形で実行可能であることを特徴とする
WebAssemblyサポートの初期実装は、既存のasm.js(英語版)とPNaClをベースとしている


フォーマット

  • WASM ... バイナリフォーマット
  • WAT/(WAST) ... テキスト表現
1+2を計算するwatの例
(module
  ;; ---- export main function  ---
  (export "exported_main" (func $main))
  (func $main (result i32)
    (i32.add
      (i32.const 1)
      (i32.const 2)
    )
  )
)

実装方式

  • スタックマシン ... WASM
  • レジスタマシン ... LLVM


WebAssembly 以前のブラウザプラグイン

他のプラグインと比べた特徴

  • 制約を設ける ... サンドボックス、直接描画無し
  • 制約を取り払う ... バイトコード+JITコンパイラ→プラットフォーム独立
  • 拡張性
    • JavaScriptとの相互呼び出しが可能
    • JavaScriptと両方アクセスできるメモリー領域(バイト列)の読み書きが可能

WASMへの移行の流れ

独自プラグインはサポート終了の動き

ブラウザの高速な拡張機能としてWASMが推奨されている

  • Chrome, Firefox, Safari, (Edge) がそれぞれサポートを表明

WASMの生成


WASMを手書き

  • WAT を手書き
  • WASM(バイナリに変換)
    • binaryen に含まれる wasm-as で変換
  • WASMを実行
    • ブラウザで
    • Node.js で
sample.wat
(module
  ;; ---- builtin func imports ---
  (func $putn (import "imports" "imported_putn") (param i32))

  ;; ---- export main function  ---
  (export "exported_main" (func $main))
  (func $main (result i32)
    (call $putn
      (i32.add
        (i32.const 1)
        (i32.const 2)
      )
    )
    (i32.const 111) ;; return code
  )
)
ブラウザで実行
const imports = {
  imported_putn: function(arg) { // for i32
    console.log(arg);
  }
};

fetch('sample.wasm').then(response =>
  response.arrayBuffer()
).then(bytes => WebAssembly.instantiate(bytes, { imports: imports })
).then(result => {
  let ret = result.instance.exports.exported_main();
  console.log('ret=' + ret);
});
Node.jsで実行
const fs = require('fs');
let source = fs.readFileSync(filename);
let typedArray = new Uint8Array(source);

const imports = {
  imported_putn: function(arg) { // for put i32
    console.log(arg);
  }
};

WebAssembly.instantiate(typedArray, 
  { imports: imports }
).then(result => {
  let ret = result.instance.exports.exported_main();
  console.warn('ret code=' + ret);
  process.exit(ret);
}).catch(e => {
  console.log(e);
});

デモ

  • fizzbuzz
  • ミニnode.js --> WASM 化した例

事例


おわりに

  • WASMはFlashに替わって、色々使われそう
  • Go, Rust, C++ をWASM化して使えると嬉しいかも