WebAssembly

What is it?

What is it good for?

Hendrik Sollich
preface
Background
JavaScript Performance

Why do you use JavaScript?

  1. βœ… it's convenient
  2. βœ… it's async
  3. βœ… it comes with every browser
  4. πŸ’” not because it's fast, it's not*
    * native browser APIs don't count
  5. βœ… competing implementations

Lin Clark "A cartoon intro to WebAssembly"

Lin Clark "A cartoon intro to WebAssembly"
history: asm.js

doing less

simplified JavaScript: asm.js

... can be used as a low-level,
efficient target language for compilers.

The asm.js language provides an abstraction similar to the C/C++ virtual machine: a large binary heap with efficient loads and stores, integer and floating-point arithmetic, first-order function definitions, and function pointers.

asm.js spec (faq)
... a small, strict subset of JavaScript that only allows things like `while`, `if`, numbers and top level functions.
[...] It does not allow objects, strings, closures, and basically anything that requires heap allocation. mdn

asm.js example

function MyAsmModule(stdlib, foreign, heap) {
    "use asm";
    // module body...
    return {
        export1: f1,
        // ...
    };
}
function add1(x) {
    x = x|0; // x : int
    return (x+1)|0;
}
var heap = new ArrayBuffer(0x10000);          // 64k heap 
asm.js spec

so we're compiling some native language to JavaScript that looks something like C so that
the JavaScript Engine can compile it in the Browser

after it has been downloaded

limitations of asm.js

  • it is not assembly
  • but it is JavaScript
  • 🧐
  • still JavaScript syntax
  • still have to parse
  • larger download size
  • optimizations vary
  • but easier to JIT πŸ€·πŸ½β€β™‚οΈ
webassembly logo

What Is WebAssembly?

... a simple machine model and executable format with an extensive specification . It is designed to be portable, compact, and execute at or near native speeds
...low-level, assembly-like language rust wasm book
WebAssembly

consequent step

after asm.js

  1. smaller download size
  2. easier to parse
  3. real assembly
  4. similar vm model
  5. even faster

Alon Zakai @mozilla hacks
"Why WebAssembly is Faster Than asm.js"
bonus: "A WebAssembly Toolchain Story"
WebAssembly Startup
Lin Clark "What makes WebAssembly fast?"
youtube 6v4E6oksar0 compiling the web - Google IO'17
performance

Performance vs ...

WASM vs JavaScript

it's 30x Faster
WebAssembly is β€œ30X” Faster than JavaScript

WASM vs asm.js

wasm vs asm.js Mind the Gap

WASM vs Native

...of the 24 benchmarks evaluated, seven run within 10% of native execution and almost all of them run less than 2Γ— slower.

Bringing the web up to speed
wasm vs native Mind the Gap
discussion
### Pros * strongly typed * faster loading * better performance * simpler language model * precompiled, preoptimized * fewer allocations * [what makes WASM fast?](https://hacks.mozilla.org/2017/02/what-makes-webassembly-fast/) * no GC * target for existing native code * strong isolation model * new languages on the web * better tooling
### cons * some weirdness [0 is a valid address](https://00f.net/2018/11/25/webassembly-doesnt-make-unsafe-languages-safe/) * less transparency on the web * possiblity for proprietary code in your browser

Isn't WASM just like JavaApplets or Flash? no

  • it's part of the browser
  • no plugins, no extra attack surface
  • sandboxed just like JavaScript
  • not owned by other companies like Flash or Java
  • standard, ergo part of "the web"
kudos steve klabnik

πŸ•ΊAWSM!πŸ’ƒ

capabilities

and now?

πŸ€” what can we do with it?

... everything the Web has to offer

including DOM Apis, WebGL, WebAudio, Canvas, everything you can access from JavaScript

what can we not do with it?

⏳ not yet
SIMD* 🐦
threads**
x64 binaries
🚫 not ever
everything you couldn't do* in JavaScript
udp*
syscalls: fs, clock, etc*
more precise timers*

use cases

Web, Binary
Binary protocols, parsers
Audio*/Video/Image Processing
Cryptography
Computer vision
Emulation: e.g. Gameboy or x86
Web, High Performance
CAD, Science, Games
Low latency apps: VR
As a VM
wasmjit or wasmer
CloudABI
in the ☁️Cloud
on cloudflare workers
in AWS Lambda*
More
even moar

🏘🐘 Port your Desktop code to the Web

Where is it already used?

web-dsp

http://tiny.cc/webdsp

rnnoise*

https://people.xiph.org/~jm/demo/rnnoise/

*here asm.js

picovoice

wake word demo

Conclusion

  • WebAssembly is a new Powerful tool
  • it's a Standard (unlike asm.js, Flash, JavaApplets or NaCL)
  • it's a compliment to JavaScript
  • it's still a browser, you will get better performance but no new capabilities
  • Everybody is doing it
  • it's not just for the Web (see e.g. CloudABI)

😁 Lets start HackingπŸ”¨

πŸ‘¨β€πŸ’»πŸ‘©β€πŸ’»πŸ‘¨πŸΎβ€πŸ’»πŸ‘¨πŸ½β€πŸ’»πŸ‘©πŸ½β€πŸ’»πŸ‘¨πŸΌβ€πŸ’»πŸ‘¨πŸΏβ€πŸ’»

πŸ‘¨πŸΏβ€πŸ’»πŸ‘©πŸΏβ€πŸ’»πŸ‘©πŸΌβ€πŸ’»πŸ™‹πŸ»β€β™‚οΈπŸ‘¨πŸ»β€πŸ’»πŸ‘©πŸ»β€πŸ’»πŸ‘©πŸΎβ€πŸ’»

building WebAssembly

compiling

artisan WebAssembly

Β«WATΒ»

(module
  (func $i (import "imports" "i") (param i32))
  (func (export "e")
    i32.const 42
    call $i))

emscripten logo

llvm logo *
languages

languages

WebAssembly Studio

WebAssemblyStudio webassembly.studio
go

Go

AssemblyScript logo

AssemblyScript

almost but not quite entirely unlike TypeScript

AssemblyScript: Limitations*

  • no union types
  • no any or undefined
  • Primitive and Reference Types
  • Memory Management
import "allocator/tlsf";
var ptr = memory.allocate(64);
//...
memory.free(ptr);
rust wasm

Rust for WebAssembly

browser API

How does it get into the browser?

<html>
    <head>
        <script src="example.wasm" type="application/wasm"/>
    </head>
</html>
Nope!!! There is no integration with ES Modules yet 28.02.2019
πŸ™„ sorry
  1. Get the .wasm bytes into a typed array or ArrayBuffer
  2. Compile the bytes into a WebAssembly.Module
  3. Instantiate the WebAssembly.Module with imports to get the callable exports
🀯
webassembly.org
modules by hand
fetch('simple.wasm')
    .then(response => response.arrayBuffer())
    .then(bytes => WebAssembly.instantiate(bytes, {}))
    .then(results => results.instance.exports);
mdn
await!
const obj = await WebAssembly.instantiateStreaming(
    fetch('simple.wasm'),
    importObject
);

obj.instance.exports.exported_func();
mdn

what is that importObject ?

const importObject = {
    env: {
        logger: (str) => console.info(str)
    },
}; 
πŸ“— Understanding the JS API

how do I talk to WebAssembly?

just do a bunch of FFI 😨 because the you have to tunnel everything 😩through an essentially 😱 C-like interface ffi
πŸ™‡ you don't even get strings
it's assembly after all πŸ€·β€β™‚οΈ
jumping ferris

exposing a c-like interface shy ferris

#[no_mangle]
pub fn add(a: i32, b: i32) -> i32 {
    a + b + 100
}
// import { add } from 'rust-lib.wasm';
const { add } = await fetch('rust-lib.wasm')
    .then(response => response.arrayBuffer())
    .then(bytes => WebAssembly.instantiate(bytes))
    .then(result => result.instance.exports);

console.dir(add(1,2)); // β†’ 103

FFI safetyfallen over ferris

const importObject = { env: {
    logger_num: (num) => console.info('logger_num', num),
    logger_str: (str) => console.warn('logger_str', str),
}}
extern "C" {
    fn logger_num(output: i32);
    fn logger_str(output: &str);
}

#[no_mangle]
pub unsafe fn speak() {
    logger_num(42); // 42
    logger_str("42"); // 1048576 ????
}
jumping ferris

codegen to the rescue

hello ferris rustwasm toolbox*

  • wasm-bindgen
  • web-sys & js-sys
  • wasm-pack
  • twiggy,* wee_alloc,* wasm-snip,*
  • @fixgen and @ag_dubs

wasm-bindgenπŸ“•

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
extern "C" {
    fn alert(s: &str);
}

#[wasm_bindgen]
pub fn greet(name: &str) {
    alert(&format!("Hello, {}!", name));
}

wasm-bindgen: exporting classes

#[wasm_bindgen]
pub struct Person {
    name: String, // UTF-8
}

#[wasm_bindgen]
impl Person {
    #[wasm_bindgen(constructor)]
    pub fn new(name: String) -> Person {
        Self { name }
    }

    pub fn get_name(&self) -> String {
        self.name.to_owned()
    }
}
import { Foo } from './my_module';
const p = new Person('hendrik');
console.log(p.get_name());

web-sysπŸ“• / js-sysπŸ“•

#[wasm_bindgen(start)]
pub fn run() -> Result<(), JsValue> {
    let window = web_sys::window().unwrap();
    let document = window.document().unwrap();
    let body = document.body().unwrap();

    let val = document.create_element("p")?;
    val.set_inner_html("Hello from Rust!");

    body.append_child(&val)?;

    Ok(())
}

wasm-packπŸ“•

wasm-pack demo

AWSM-Gorillas

STOP! Demo Time

Have an Awsm day!

waving ferris
bonus

binary sizes

binaryenπŸ”—
wasm-opt
wabtπŸ”—
wasm-strip
rust wasm
wee_alloc
twiggy wasm size profiler
wasm-snip replace functions with unreachable

WebAssembly for Isolation

  • UNIX is unsafe
  • Binaries can open Files and NetworkSockets themselves
  • VMs or Docker?
  • JavaScript/wasm isolation model
  • CloudABI
  • WASMER
  • CloudABI @ 32c3