WebAssembly

Goals

  • Rapido, eficiente y portable. wasm puede ser ejecutado con una velocidad cercana al codigo nativo a traves de diferentes plataformas utilizando las diferentes capacidaddes de harddware de los ususarios
  • Legible y debugueable. Si bien wasm es un lenguaje de bajo nivel, tiene un formato de texto que puede ser leido por humanos (la especificacion aun no esta termianda)
  • Seguro. wasm se ejecuta en un entorno seguro.
  • No debe romper la web

Como encaja wasm en la web

Se puede pensar que una web esta formada por 2 cosas:

  • Una maquina virtual, que ejecuta el codigo de la web, generalmente JS
  • Un conjunto de WebAPI's que pueden controlar el dispositivo, el navegador. Por ejemplo, DOM, WebGL, ServiceWorkers, LocalStorage, etc.

Con la llegada de wasm, la maquina virtual tendra que correr 2 tipos diferentes de codigo:

JS y wasm

 

  • JavaScript es un lenguaje de alto nivel, muy flexible con muchas ventajas, y que ademas cuenta con un enorme ecosistema de framworks, librerias, etc.
  • wasm es un lenguaje de bajo nivel, con un formato buinario compacto ser ejecutado con perfomances cercanas a las antivas, y provee, un target donde ser compilado por lenguajes con manejo de memoria a bajo nivel, como C++ y Rust, para poder ser corridos en la web.
  • La  WebAssembly JavaScript API envuelve codigo wasm con funciones de JS que pueden ser llamadas normalmente, y el codigo wasm puede importar funciones y llamar soncronicamente funciones de JS.

WebAssembly is a different language from JavaScript, but it is not intended as a replacement.

conceptos wasm

Conceptos

  • Module: Es un codigo binario que fue compilado en el navegador, y convertido en codigo que peude ser utilizado por la computadora. Los modulos no podeen estado, por lo tanto pueden ser compartidos entre ventanas, pestañas, serviceWorkers, o cacheados.
  • Memory: Un ArrayBuffer variable en tamaño, que tiene los bytes que son leidos y escritos por el modulo wasm, a traves de instrucciones de la memoria de bajo nivel.
  • Table: Un array de referencias, de tamaño variable, que por cuestiones de portabilidad y seguridad no puede ser guardado en Memory.
  • Instance: Es la ejecucion de un module, junto con su estado, incluyendo sus Memory, sus Tables y los valores que importo.

Usando wasm

Aun no hay una manera de que el navegador traiga los modulos de wasm.
La forma actual de hacerlo es:

  1. Pedir el archivo a traves de fetch o XMLHttpRequest.

  2. crear un ArrayBuffer que contenga el codigo binario.

  3. compilarlo usando WebAssembly.instantiate().

Esto es analogo

new Function(string)
pero estamos cambiando un string de carcteres (codigo JS) por una array de bytes (codigo wasm)

fetch('module.wasm').then(response =>
  response.arrayBuffer()
).then(bytes =>
  WebAssembly.instantiate(bytes, importObject)
).then(results => {
    // Call an exported function:
  results.instance.exports.exported_func();

  // or access the buffer contents of an exported memory:
  var i32 = new Uint32Array(results.instance.exports.memory.buffer);

  // or access the elements of an exported table:
  var table = results.instance.exports.table;
  console.log(table.get(0)());
});

en que se diferencia JS de wasm (en teoria)

JS

wasm

decoding WebAssembly takes less time than parsing JavaScript.

Compiling and optimizing takes less time because WebAssembly is closer to machine code than JavaScript and already has gone through optimization on the server side.

Reoptimizing doesn’t need to happen because WebAssembly has types and other information built in, so the JS engine doesn’t need to speculate when it optimizes the way it does with JavaScript.

executing often takes less time because there are fewer compiler tricks and gotchas that the developer needs to know to write consistently performant code, plus WebAssembly’s set of instructions are more ideal for machines.

garbage collection is not required since the memory is managed manually.

Ejemplos

<!doctype html>
  <title>WASM Collision Demo</title>
  <body style="margin:0; overflow: hidden">
    <canvas id="canvas" style="width: 100vw; height: 100vh; display:block;"></canvas>
      <script>
    fetch('https://cdn.rawgit.com/guybedford/wasm-intro/f61eb0d0/1-loading-wasm-fn/test.wasm')
    .then(res => {
      if (res.ok)
        return res.arrayBuffer();
      throw new Error(`Unable to fetch WASM.`);
    })
    .then(bytes => {
      return WebAssembly.compile(bytes);
    })
    .then(module => {
      return WebAssembly.instantiate(module);
    })
    .then(instance => {
      window.wasmSqrt = instance.exports.sqrt;
    });
  </script>
    <p>
        for(i=0;i<10;i++){
	    var value = Math.random()*Math.random()*1000000;
	    console.time('wasmSqrt');window.wasmSqrt(value+0);console.timeEnd('wasmSqrt');
	    console.time('Mathsqrt');Math.sqrt(value+"0");console.timeEnd('Mathsqrt');
	    console.log('-----------')
	}
</p>
</body>

deck

By Pablo Hiyano

deck

  • 505