WebAssembly

Mikołaj Rozwadowski

1 kwietnia 2019

Aplikacje internetowe

package main;

public class Main {
    public static void main(String args[]) {
        System.out.println("Hello world!");
    }
}
<h1>Hello world!</h1>
1.0 === 1
1 + '1' === '11'
[] + [] === ''
[] + {} === '[object Object]'
{} + [] === 0
help-with-circle
int fib(int n) {
  if (n <= 1) return 1;
  return fib(n - 1) + fib(n - 2);
}
➜  ~ xxd program.wasm 
00000000: 0061 736d 0100 0000 0186 8080 8000 0160  .asm...........`
00000010: 017f 017f 0382 8080 8000 0100 0484 8080  ................
00000020: 8000 0170 0000 0583 8080 8000 0100 0106  ...p............
00000030: 8180 8080 0000 0790 8080 8000 0206 6d65  ..............me
00000040: 6d6f 7279 0200 0366 6962 0000 0ac0 8080  mory...fib......
00000050: 8000 01ba 8080 8000 0101 7f41 0121 0102  ...........A.!..
00000060: 4020 0041 0248 0d00 2000 4102 6a21 0041  @ .A.H.. .A.j!.A
00000070: 0121 0103 4020 0041 7d6a 1000 2001 6a21  .!..@ .A}j.. .j!
00000080: 0120 0041 7e6a 2200 4103 4a0d 000b 0b20  . .A~j".A.J.... 
00000090: 010b                                     ..
(module
 (table 0 anyfunc)
 (memory $0 1)
 (export "memory" (memory $0))
 (export "fib" (func $fib))
 (func $fib (; 0 ;) (param $0 i32) (result i32)
  (local $1 i32)
  (set_local $1
   (i32.const 1)
  )
  (block $label$0
   (br_if $label$0
    (i32.lt_s
     (get_local $0)
     (i32.const 2)
    )
   )
   (set_local $0
    (i32.add
     (get_local $0)
     (i32.const 2)
    )
   )
   (set_local $1
    (i32.const 1)
   )
   (loop $label$1
    (set_local $1
     (i32.add
      (call $fib
       (i32.add
        (get_local $0)
        (i32.const -3)
       )
      )
      (get_local $1)
     )
    )
    (br_if $label$1
     (i32.gt_s
      (tee_local $0
       (i32.add
        (get_local $0)
        (i32.const -2)
       )
      )
      (i32.const 3)
     )
    )
   )
  )
  (get_local $1)
 )
)
const imports = {};

WebAssembly
  .instantiateStreaming(fetch('program.wasm'), imports)
  .then(({ instance }) => {
    const { fib } = instance.exports;
    console.log(fib(13));
  });

Dlaczego WebAssembly
jest szybki?

Dlaczego JavaScript
jest wolny?

Bufory i tablice statyczne w JavaScripcie

const a = new Int32Array(5);
a[0] = 5;
a[1] = 3.14;
a[7] = 2;
console.log(a);
// => Int32Array [5, 3, 0, 0, 0]
Int8Array
Uint8Array
Uint8ClampedArray
Int16Array
Uint16Array
Int32Array
Uint32Array
Float32Array
Float64Array
const buffer = new ArrayBuffer(4);
const floats = new Float32Array(buffer);
const ints = new Int32Array(buffer);
const bytes = new Uint8Array(buffer);

floats[0] = 0.1;

console.log(floats);
// => Float32Array [ 0.10000000149011612 ]
console.log(ints);
// => Int32Array [ 1036831949 ]
console.log(bytes);
// => Uint8Array [ 205, 204, 204, 61 ]

Emscripten

asm.js

function GeometricMean(stdlib, foreign, buffer) {
  "use asm";
  var exp = stdlib.Math.exp;
  var log = stdlib.Math.log;
  var values = new stdlib.Float64Array(buffer);
  function logSum(start, end) {
    start = start|0;
    end = end|0;
    var sum = 0.0, p = 0, q = 0;
    for (p = start << 3, q = end << 3; (p|0) < (q|0); p = (p + 8)|0) {
      sum = sum + +log(values[p>>3]);
    }
    return +sum;
  }
  function geometricMean(start, end) {
    start = start|0;
    end = end|0;
    return +exp(+logSum(start, end) / +((end - start)|0));
  }
  return { geometricMean: geometricMean };
}
module.exports = GeometricMean;
emcc -O3 \
     -s WASM=1 \
     -s EXTRA_EXPORTED_RUNTIME_METHODS='["cwrap"]' \
     fib.c

Demo

Więcej informacji

Dziękuję za uwagę!