Kino 7 – Friday, 2 pm – Buzzing Technologies
Konstantin Möllers @ksm2 @k_moellers
Konstantin Möllers
Buzzing Technologies
Konstantin Möllers
Performance Engineer @ Baqend
Master of Science @ Uni Hamburg
Professional working experience for 6 years
WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable target for compilation of high-level languages like C/C++/Rust, enabling deployment on the web for client and server applications.
Imperative
|
Stack-Based
|
https://www.chromestatus.com/feature/5804334163951616 https://developer.microsoft.com/en-us/microsoft-edge/platform/status/streamsapireadablestream/ https://webkit.org/status/#feature-readable-streams
|
|
JS and Wasm are a perfect match for hybrid apps!
number
i32
i64
f32
f64
boolean
i32
string
function
object
But how do I create a Wasm binary and use it?
async function initWebAssembly(wasmUrl: string, importObject?: any) {
const response = await fetch(wasmUrl)
const bytes = await response.arrayBuffer()
// Compile the bytecode to a WASM module
const module = await WebAssembly.compile(bytes)
// Wake up the module: „importObject“ is bound to the module
return new WebAssembly.Instance(module, importObject)
}
// For the Fibonacci Example:
// Call the exported function “fibonacci” with 6.
initWebAssembly('fibonacci.wasm')
.then(instance => instance.exports.fibonacci(6))
.then(console.log)
// fibonacci.c
int fibonacci(int n) {
if (n <= 0) return 0;
if (n == 1) return 1;
return fibonacci(n - 1) + fibonacci(n - 2);
}
$ emcc fibonacci.c \
-s WASM=1 \
-s ONLY_MY_CODE=1 \
-s EXPORTED_FUNCTIONS="['_fibonacci']" \
-Os \
-o fibonacci.c.js
// Usage from JavaScript
const response = await fetch('./fibonacci.c.wasm')
const instance = await WebAssembly.instantiateStreaming(response)
const result = instance.exports._fibonacci(21, 21) // Mind the "_"!
console.log(result) // Logs "42"
// fibonacci.rs
#[no_mangle]
pub fn fibonacci(n: i32) -> i32 {
match n {
std::i32::MIN...0 => 0,
1 => 1,
_ => fibonacci(n - 1) + fibonacci(n - 2),
}
}
$ rustc -O --crate-type=cdylib --target=wasm32-unknown-unknown \
-o fibonacci.rs.wasm \
fibonacci.rs
// Usage from JavaScript
const response = await fetch('./fibonacci.rs.wasm')
const instance = await WebAssembly.instantiateStreaming(response)
const result = instance.exports.fibonacci(21, 21)
console.log(result) // Logs "42"
// fibonacci.asm.js
function fibonacci() {
"use asm";
function fibonacci(n) {
n = n | 0;
if (n <= 0) return 0 | 0;
if (n == 1) return 1 | 0;
return ((fibonacci(n - 1) | 0) + (fibonacci(n - 2) | 0)) | 0;
}
return { fibonacci: fibonacci };
}
$ asm2wasm fibonacci.asm.js -Os -o fibonacci.asm.js.wasm
// Usage from JavaScript
const response = await fetch('./fibonacci.asm.js.wasm')
const instance = await WebAssembly.instantiateStreaming(response)
const result = instance.exports.fibonacci(21, 21)
console.log(result) // Logs "42"
;; fibonacci.wat
(func $fibonacci
(export "fibonacci") ;; Function export name
(param $n i32) (result i32) ;; Signature: (i32) -> i32
;; If condition $n ≤ 0
(if (i32.le_s (get_local $n) (i32.const 0))
(then
(return (i32.const 0))))
;; If condition $n = 1
(if (i32.eq (get_local $n) (i32.const 1))
(then
(return (i32.const 1))))
(return
(i32.add
(call $fibonacci ;; Recursive function call
(i32.sub (get_local $n) (i32.const 1)))
(call $fibonacci
(i32.sub (get_local $n) (i32.const 2))))))
$ wat2wasm fibonacci.wat -o fibonacci.wat.wasm
Mandelbrot Fractal
with Rust + WebAssembly
For each pixel c, calculate
Which is the same as
until |zn| > 2, or a limit of 40 iterations occurs.
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "./greet")]
extern {
pub fn greet(greeted: &str) -> String;
}
#[wasm_bindgen]
pub fn say_hi(name: &str) -> String {
let greeting = greet(name);
format!("{}! Nice to see you at my talk!", greeting)
}
// greet.js
export function greet(name) {
return `Hello, ${name}`
}
// index.js
import('./wasm-package')
.then(pkg => pkg.say_hi('Markus'))
.then(msg => console.log(msg))
Average Latency | 561 ms | 396 ms | 569 ms | 331 ms | 994 ms | 295 ms |
---|---|---|---|---|---|---|
– 42 % | – 72 % | – 237 % | ||||
Median Latency | 557 ms | 388 ms | 558 ms | 329 ms | 984 ms | 293 ms |
– 44 % | – 70 % | – 236 % | ||||
Throughput | 1.78/s | 2.52/s | 1.76/s | 3.02/s | 1.01/s | 3.39/s |
+ 42 % | + 72 % | + 236 % |
Konstantin Möllers
ksm@baqend.com
@ksm2
@k_moellers