WEBASSEMBLY The Swiss Army Knife of Browser Apps
WEBASSEMBLY�� The Swiss Army Knife of Browser Apps All photographs in this deck © 2019 Jeremy Likness. All Rights Reserved. @Jeremy. Likness
WHAT IF I TOLD YOU…
…YOU CAN RUN CODE IN YOUR BROWSER AT NEARNATIVE SPEEDS… (WITHOUT PLUGINS)
…AND USE THE LANGUAGE OF YOUR CHOICE? Zen Garden Demo: https: //jlik. me/fzg
In the beginning … const compute. Prime = () => { var last. Prime = -1; for (let i = 2; i < 50000; i+=1) { let is. Prime = true; for (let j = i-1; j >= 2; j-=1) { if (i % j == 0) { is. Prime = false; break; } if (is. Prime) { last. Prime = i; } } return last. Prime; }
Along came asm. js …
Along came asm. js … C/C++
Along came asm. js … C/C++ Clang
Along came asm. js … C/C+ + Clang LLVM
Along came asm. js … C/C++ Clang LLVM Emscripte n
Along came asm. js … C/C++ Clang LLVM Emscripte n Asm. js
primes. c int compute. Primes. Asm() { int last. Prime; int i; int j; int is. Prime; for (i = 2; i < 50000; i = i+1) { is. Prime = 1; for (j = i-1; j >= 2; j--) { if (i % j == 0) { is. Prime = -1; break; } } if (is. Prime == 1) { last. Prime = i; } } return last. Prime; }
BUILD ASM. JS Demo https: //github. com/Jeremy. Likness/blazor-wasm/tree/master/primes
primes. js function _compute. Primes. Asm() { var $0 = 0, $10 = 0, $11 = 0, $12 = 0, $13 = 0, $14 = 0, $15 = 0, $16 = 0, $17 = 0, $18 = 0, $19 = 0, $20 = 0, $21 = 0, $3 = 0, $4 = 0, $5 = 0, $6 = 0, $7 = 0; var $8 = 0, $9 = 0, label = 0, sp = 0; sp = STACKTOP; STACKTOP = STACKTOP + 16|0; if ((STACKTOP|0) >= (STACK_MAX|0)) abort. Stack. Overflow(16|0); $1 = 2; while(1) { $4 = $1; $5 = ($4|0)<(50000); if (!($5)) { break; } $3 = 1; $6 = $1; $7 = (($6) - 1)|0; $2 = $7; while(1) { $8 = $2; $9 = ($8|0)>=(2); if (!($9)) { break; } $10 = $1; $11 = $2; $12 = (($10|0) % ($11|0))&-1; $13 = ($12|0)==(0); if ($13) { label = 6; break; } $14 = $2; $15 = (($14) + -1)|0; $2 = $15; } if ((label|0) == 6) { label = 0; $3 = -1; } $16 = $3; $17 = ($16|0)==(1); if ($17) { $18 = $1; $0 = $18; } $19 = $1; $20 = (($19) + 1)|0; $1 = $20; } $21 = $0; STACKTOP = sp; return ($21|0); }
Java. Script vs. asm. js in Chrome Time to Compute (ms) 4000 3500 3000 2500 2000 1500 1000 500 0 Primes Java. Script asm. js
Then, in 2017 …
Binary A Quick Look Back… 1010 1101 0010 0000 1101 0000
1010 1101 0010 0000 1101 0000 $AD $20 $D 0 Hexadecim al Binary A Quick Look Back…
A Quick Look Back… LDA $D 020 Assembly $AD $20 $D 0 Hexadecimal Binary 1010 1101 0010 0000 1101 0000
A QUICK LOOK BACK…
A QUICK LOOK BACK…
primes. wasm. c int compute. Primes. Wasm() { int last. Prime; int i; int j; int is. Prime; for (i = 2; i < 50000; i = i+1) { is. Prime = 1; for (j = i-1; j >= 2; j--) { if (i % j == 0) { is. Prime = -1; break; } } if (is. Prime == 1) { last. Prime = i; } } return last. Prime; }
Wasm is Binary, this is a textual visualization (module (type $t 0 (func)) (type $t 1 (func (result i 32))) (func $__wasm_call_ctors (type $t 0)) (func $compute. Primes. Wasm (export "compute. Primes. Wasm") (type $t 1) (result i 32) (local $l 0 i 32) (local $l 1 i 32) (local $l 2 i 32) (local $l 3 i 32) (local $l 4 i 32) i 32. const 1 set_local $l 0 i 32. const 2 set_local $l 1 loop $L 0 get_local $l 0 set_local $l 2 block $B 1 block $B 2 loop $L 3 get_local $l 2 i 32. const 2 i 32. lt_s br_if $B 2 get_local $l 1 get_local $l 2 i 32. rem_s set_local $l 3 get_local $l 2 i 32. const -1 i 32. add set_local $l 2 get_local $l 3 br_if $L 3 end get_local $l 0 i 32. const 1 i 32. add set_local $l 0 get_local $l 1 i 32. const 1 i 32. add tee_local $l 1 i 32. const 50000 i 32. ne br_if $L 0 br $B 1 end get_local $l 1 set_local $l 4 get_local $l 0 i 32. const 1 i 32. add set_local $l 0 get_local $l 1 i 32. const 1 i 32. add tee_local $l 1 i 32. const 50000 i 32. ne br_if $L 0 end get_local $l 4) (table $T 0 1 1 anyfunc) (memory $memory (export "memory") 2) (global $g 0 (mut i 32) (i 32. const 66560)) (global $__heap_base (export "__heap_base") i 32 (i 32. const 66560)) (global $__data_end (export "__data_end") i 32 (i 32. const 1024)))
A QUICK LOOK AT THE BASICS Introducing Web. Assembly Studio: https: //webassembly. studio/
Stack-Based Programming
Stack-Based Programming get_local $lhs 2
Stack-Based Programming 4 2 get_local $rhs
Stack-Based Programming 4 6 2 i 32. add
Wasm vs. asm. js Byte code (no precompilation/script parsing) Compact delivery (smaller file size) Wasm-specific instruction set (not constrained by Java. Script)
WASM AND PERFORMANC E Demo https: //github. com/Jeremy. Likness/b lazor-wasm/tree/master/primes
Wasm exposes memory via heaps Byte: 0 1 2 3 4 5 6 7 Value HEAP 8 0 1 2 3 4 5 6 7 -1 HEAP 16 0 HEAP 32 0 HEAPU 8 0 HEAPU 16 0 1 2 3 -256 1 1 2 1 3 4 2 -32769 5 6 3 7 128 32768 HEAPU 32 0 1 65537 HEAPF 32 0 1 -3. 1415 HEAPF 64 0 4. 669
Java. Script provides typed arrays Java. Script Array BYTES_PER_ELEME NT HEAP 8 Int 8 Array 1 HEAP 16 Int 16 Array 2 HEAP 32 Int 32 Array 4 HEAPU 8 Uint 8 Array 1 HEAPU 16 Uint 16 Array 2 HEAPU 32 Uint 32 Array 4 HEAPF 32 Float 32 Array 4 HEAPF 64 Float 64 Array 8
Web. Assembly application: Two ways to allocate memory in Wasm • unsigned char x[2] = 2 bytes allocated, access via HEAPU 8 • int x[2] = 8 bytes allocated, access via HEAP 32 • long x[2] = 8 bytes allocated, access via HEAP 32 • Wait, wuuuuut? Support for 64 -bit, like winter, is coming Java. Script: • Module. malloc(x) = x bytes allocated • Module. malloc(4 * Float 32 Array. BYTES_PER_ELEMENT) = 32 bytes allocated as 4 floating-point numbers on HEAPF 32
THE CHAOS GAME Demo https: //github. com/Jeremy. Likness/wasm-trees
Automated Builds https: //github. com/Jeremy. Likness/wasm-trees/blob/master/azure-pipelines. yml
Go from 2007 Statically typed and compiled language Memory safety Garbage collection Structural typing Concurrency Runtime built-in
“Operating System” = Java. Script “Architecture” = Wasm Gophers went Wasm in 2018 import “syscall/js” js. Func type Js. Func. Of for conversion js. Global() Get, Set, and Call
PLASMA IN GO Demo https: //github. com/Jere my. Likness/plasmawasm go
Automated Builds https: //github. com/Jeremy. Likness/Plasma. Wasm. Go/blob/master/azure-pipelines. yml
RUN A 1980 S VM IMPLEMENTED IN GO ON WASM “Open the mailbox. ” https: //github. com/Jeremy. Likness/zmachin e
A little Rusty in 2010 C++ syntax Memory safety Most ❤ in Stack. Overflow for past four years yes, there ( are problems with the survey) No null pointers Reference counting for memory management Explicit mutability Type ownership
No runtime so smaller Wasm sizes wasm-pack for building Wasm from Rust wasm-bindgen for automated interop (both ways!) Rust �� � Web. Assembly ��
PLASMA IN RUST Demo https: //github. com/Jere my. Likness/Plasma. Was m. Rust
The Rust Payload https: //github. com/Jeremy. Likness/Plasma. Wasm. Rust/blob/master/azurepipelines. yml
…then in 2017 . NET
Wait. Why use. NET for browser apps? Modern languages (C#, F#) Full-stack . NET ecosystem Performanc e Tools Stable & mature
“Blazor” preview project Full-stack web development with. NET via Web. Assembly No plugin or code transpilation Works in all modern browsers including mobile browsers Browser + Razor = Blazor!
@Jeremy. Likness
@Jeremy. Likness
@Jeremy. Likness
@Jeremy. Likness
@Jeremy. Likness
DEPENDENCY INJECTION SERVER-SIDE RENDERING COMPONENT MODEL FORMS & VALIDATION DEBUGGING ROUTING PUBLISHING Blazor UNIT TESTING ASSEMBLY TRIMMING INTELLISENSE & TOOLING LAYOUTS AUTO REBUILD JAVASCRIPT INTEROP COMPONENT PACKAGES
DEMO: BLAZOR IN ACTION. NET on Wasm with Java. Script interactions https: //github. com/Jeremy. Likness/blazorwasm
Why Web. Assembly? Byte code (no precompilation/script parsing) Compact delivery (smaller file size) Wasm-specific instruction set (not constrained by Java. Script)
https: //blog. jeremylikness. com/ @Jeremy. Likness@microsoft. com https: //github. com/Jeremy. Likness/blazor-wasm https: //github. com/Jeremy. Likness/wasm-trees https: //github. com/Jeremy. Likness/Plasma. Wasm. Go https: //github. com/Jeremy. Likness/Plasma. Wasm. Rust https: //github. com/Jeremy. Likness/zmachine
- Slides: 60