ted.neward@newardassociates.com | Blog: http://blogs.newardassociates.com | Github: tedneward | LinkedIn: tedneward
Understand where WASM came from
Figure out how to get started with WASM
Examine some of the tools
Explore the specification
... a bytecode-inspired/influenced for browsers to execute
faster load
faster parse
faster resolution
better checking and verification
standardized across browsers
defined in text and binary format
intended as a target for language compilers/transpilers
Fast, safe, and portable semantics
fast, safe, open, well-defined, hardware-, language-, and platform-independent
Efficient and portabld representation
compact, modular, efficient, streamable, parallelizable, and portable
(and easy to inspect and debug)
slow
non-standard
"nothing like Java"
Sun debuted the "HotJava" browser
had everybody thinking "applets-to-CORBA-to-database"
applets had extremely weak UI support
Java had to be installed in the browser
Sun's battles with Microsoft split the industry
If you couldn't do it in HTML, don't do it
Server-side rendering was the only game in town
the struggle was real
"modern" Javascript usage starts to normalize the browsers
minor UI effects (animations, etc) begin to wake up our expectations
users are really, really, really tired of server round-trips
https://www.hanselman.com/blog/JavaScriptIsAssemblyLanguageForTheWebSematicMarkupIsDeadCleanVsMachinecodedHTML.aspx
browsers are ubiquitous
Javascript will never be replaced as the language of the browser
thus, target it as the output of compilation tools and such
"Project Volta" (discontinued in 2012)-- later IL2JS: https://github.com/Reactive-Extensions/IL2JS
"asm.js is a subset of JavaScript designed to allow computer software written in languages such as C to be run as web applications while maintaining performance characteristics considerably better than standard JavaScript, which is the typical language used for such applications." (Wikipedia)
targeted by Emscripten C/C++ toolchain
browsers could optimize execution by recognizing these operations
Mozilla supported this starting with v22 of their browser
involving numerous companies and Javascript luminaries
https://medium.com/javascript-scene/why-we-need-webassembly-an-interview-with-brendan-eich-7fb2a60b0723
supported in four major browsers
Chrome, IE/Edge, Mozilla, Safari
specification(s) released
Core (https://webassembly.github.io/spec/core/_download/WebAssembly.pdf)
JavaScript embedding (https://webassembly.github.io/spec/js-api/index.html)
Web embedding (https://webassembly.github.io/spec/web-api/index.html)
in other words, you usually won't write WASM "in the raw"
though, of course, you could
C/C++ (Emscripten)
gcc/g++ front-end
WASM-generating (HTML/JS) back-end
Zig (oh, fine, Rust too)
AssemblyScript (TypeScript-ish)
COBOL
others
browser is an obvious target
wasmtime
NodeJS
GraalVM
macOS: Homebrew
brew install emscripten
Linux: Linuxbrew
brew install emscripten
Windows: WSL + Linuxbrew
brew install emscripten
tool requirements
requires Python 2.7
MacOS, Linux: Should have all tools already
Windows10: Use Windows Subsystem for Linux, get python2
Fire up Git
Installing Emscripten SDK "by hand"
$ git clone https://github.com/juj/emsdk.git $ cd emsdk $ ./emsdk install latest $ ./emsdk activate latest
Write some C/C++!
#include <stdio.h> int main(int argc, char ** argv) { printf("Hello, world!\n"); return 0; }
#include <iostream> using namespace std; int main(int argc, char ** argv) { cout << "Hello world" << endl; return 0; }
Compile
$ emcc -s WASM=1 -o hello.html --emrun hello.c
... or ...
$ em++ -s WASM=1 -o hello.html --emrun hello.cpp
Then
$ emrun --no_browser --port 8080 .
Open a browser to http://localhost:8080/hello.html
a "virtual Instruction Set Architecture"
an embeddable interpreter
in this respect, very much akin to Javascript itself
many/most Javascript engines will recognize WASM
based on a stack machine
instructions manipulate values on an operand stack
instructions will pop arguments off the stack, and results onto it
decoding
validation
execution
process the distribution format
convert into an internal representation
guarantee that the module is meaninful and safe
broken into two sub-phases, each accessible as an operation in the hosting environment:
instantiation: "A module instance is the dynamic representation of a module, complete with its own state and execution stack. Instantiation executes the module body itself, given definitions for all its imports. It initializes globals, memories and tables and invokes the module’s start function if defined. It returns the instances of the module’s exports.""
invocation: "Once instantiated, further WebAssembly computations can be initiated by invoking an exported function on a module instance. Given the required arguments, that executes the respective function and returns its results."
"A WebAssembly binary takes the form of a module that contains definitions for functions, tables, and linear memories, as well as mutable or immutable global variables. Definitions can also be imported, specifying a module/name pair and a suitable type. Each definition can optionally be exported under one or more names. In addition to definitions, modules can define initialization data for their memories or tables that takes the form of segments copied to given offsets. They can also define a start function that is automatically executed."
"Code is organized into separate functions. Each function takes a sequence of values as parameters and returns a sequence of values as results. Functions can call each other, including recursively, resulting in an implicit call stack that cannot be accessed directly. Functions may also declare mutable local variables that are usable as virtual registers."
"A table is an array of opaque values of a particular element type. It allows programs to select such values indirectly through a dynamic index operand. Currently, the only available element type is an untyped function reference. Thereby, a program can call functions indirectly through a dynamic index into a table. For example, this allows emulating function pointers by way of table indices."
"A linear memory is a contiguous, mutable array of raw bytes. Such a memory is created with an initial size but can be grown dynamically. A program can load and store values from/to a linear memory at any byte address (including unaligned). Integer loads and stores can specify a storage size which is smaller than the size of the respective value type. A trap occurs if an access is not within the bounds of the current memory size."
"Under some conditions, certain instructions may produce a trap, which immediately aborts execution. Traps cannot be handled by WebAssembly code, but are reported to the outside environment, where they typically can be caught."
"A WebAssembly implementation will typically be embedded into a host environment. This environment defines how loading of modules is initiated, how imports are provided (including host-side definitions), and how exports can be accessed. However, the details of any particular embedding are beyond the scope of this specification, and will instead be provided by complementary, environment-specific API definitions."
WASM bytecode categories:
Module/structure definitions
Numeric operations
Variable instructions
Memory instructions
Control instructions
Module/structure definition
modules are made up of 0..n:
imports
exports
types
funcs
tables
mems
globals
elem
data
start
any/all may be empty
An empty module
<</home/runner/work/Slides/Slides/Content/WebAssembly/code/wat/empty.wat NOT FOUND>>
Module/structure definition
each of these sections are referenced by index
u32 in size
this includes locals (inside functions) and labels (inside functions)
indexes are often replaceable by names in WAT
Module/structure definition
types defines a vector of function types
these are function signature types
functions will declare themselves to be one of these types
future versions of WASM may add new types
start declares the start function invoked at module instantiation
exports declares all functions exported from this module
imports declares all functions needed by this module
A more reasonable module (1/2)
<</home/runner/work/Slides/Slides/Content/WebAssembly/code/wat/adder.wat NOT FOUND>>
A more reasonable module (2/2)
<</home/runner/work/Slides/Slides/Content/WebAssembly/code/wat/adder.wat NOT FOUND>>
Numeric "bases" to operations
i32, i64, f32, f64: integer and floating-point, 32- and 64-bit
these are "bases" for any numeric-related operation
in a form like {base}.{operation} {operand}
Numeric unary operations
push operands, pop operands
{base}.const {v}: push {v} (of type {base}) onto stack
drop: throws away single operand
select: selects either {a} or {b} operand depending on {c == 0}
iclz {v} (count of leading zero bits in v)
ictz {v} (count of trailing zero bits in v)
ipopcnt {v} (count of non-zero bits in v)
Numeric binary operations
add, sub, mul, div_u, div_s, rem_u, rem_s
and, or, xor, shl, shr, shr_s, rotl, irotr
abs, neg, ceil, floor, trunc, nearest, sqrt, min, max
eqz, eq, ne, lt, gt, le, ge
full list given in WASM Specification (Text Format, Instructions)
Variable instructions
global.set {idx}, global.get {idx}
get/set global #{idx} to/from top of stack
local.set {idx}, local.get {idx}
get/set local #{idx} to/from top of stack
local.tee {idx}
like local.set but also returns its argument
Memory instructions
{base}.load {memarg} | {base}.store {memarg}
load or store to linear memory
{memarg} is an offset/alignment pair
memory.size
return current size of linear memory
memory.grow
expand linear memory
Control instructions
nop: does nothing
unreachable: unconditional trap
structured instructions
block {resulttype} {instructions} end
loop {resulttype} {instructions} end
if {resulttype} {instructions} else {instructions} end
each introduces an implicit label
br {label}: unconditional branch to label
br_if {label}: conditional branch to label
br_table {label}: table-lookup branch
Control instructions
call {fnidx}: call function #{fnidx} directly
call_indrect {tableidx}: call function at {tableidx}
return: terminate local function
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly
instantiate()/instantiateStreaming(): compile and instantiate WASM
returns both Module and Instance
compile()/compileStreaming(): compiles WASM code
returns Module; does not instantiate
validate(): validate given typed array as valid WASM binary
returns true/false
Module(): another way to create a module object
Instance(): represents a module instance (state)
Memory(): linear memory for use by WASM and JS
Table(): function tables for invocation
Global(): new global for use by WASM/JS
NodeJS-based hosting
<</home/runner/work/Slides/Slides/Content/WebAssembly/./code/wat/runwat.js NOT FOUND>>
NodeJS-based hosting
<</home/runner/work/Slides/Slides/Content/WebAssembly/./code/wat/runwat.js NOT FOUND>>
Browser-based hosting
<</home/runner/work/Slides/Slides/Content/WebAssembly/./code/wat/runwat.html NOT FOUND>>
"WABT" ("wabbit")
Collection of binary tools manipulating/exploring WASM files
https://github.com/WebAssembly/wabt
"Binaryen"
Compiler toolchain for WASM written in C++ intended for others' use
https://github.com/WebAssembly/binaryen
WebAssembly.Studio
https://webassembly.studio/
C, Rust, AssemblyScript, Wat project types
wat2wasm
translate from WebAssembly text format to the WebAssembly binary format
wasm2wat
the inverse of wat2wasm, translate from the binary format back to the text format (also known as a .wat)
wasm-objdump
print information about a wasm binary. Similiar to objdump.
wasm-interp
decode and run a WebAssembly binary file using a stack-based interpreter
wat-desugar
parse .wat text form as supported by the spec interpreter (s-expressions, flat syntax, or mixed) and print "canonical" flat format
wasm2c
convert a WebAssembly binary file to a C source and header
wasm-strip
remove sections of a WebAssembly binary file
wasm-validate
validate a file in the WebAssembly binary format
wast2json
convert a file in the wasm spec test format to a JSON file and associated wasm binary files
wasm-opcodecnt
count opcode usage for instructions
spectest-interp
read a Spectest JSON file, and run its tests in the interpreter
aims to make compiling to WASM easy, fast, and effective
easy: simple C API header; can be used from Javascript
fast: internal IR optimized for performance
effective: optimizer has numerous passes to improve codegen
wasm-shell
A shell that can load and interpret WebAssembly code. It can also run the spec test suite.
wasm-as
Assembles WebAssembly in text format (currently S-Expression format) into binary format (going through Binaryen IR).
wasm-dis
Un-assembles WebAssembly in binary format into text format (going through Binaryen IR).
wasm-opt
Loads WebAssembly and runs Binaryen IR passes on it.
asm2wasm
An asm.js-to-WebAssembly compiler, using Emscripten's asm optimizer infrastructure. This is used by Emscripten in Binaryen mode when it uses Emscripten's fastcomp asm.js backend.
wasm2js
A WebAssembly-to-JS compiler (still experimental).
wasm-merge
Combines wasm files into a single big wasm file (without sophisticated linking).
wasm-ctor-eval
A tool that can execute C++ global constructors ahead of time. Used by Emscripten.
wasm-emscripten-finalize
Takes a wasm binary produced by llvm+lld and performs emscripten-specific passes over it.
binaryen.js
A standalone JavaScript library that exposes Binaryen methods for creating and optimizing WASM modules. For builds, see binaryen.js on npm (or download it directly from github, rawgit, or unpkg).
Cheerp
https://leaningtech.com/cheerp/
a commercial open-source C/C++ compiler for Web applications
https://github.com/leaningtech/cheerp-meta
AssemblyScript
language derived from TypeScript intended to be as close to WASM semantics as possible
uses JS port of binaryen
https://github.com/AssemblyScript/assemblyscript
... certainly holds a lot of promise
bytecode offers lots of room for performance improvement
WASM futures offer a lot of areas for general enhancement
... is as-yet-unclear as to its impact
could represent huge shift in client-side Web
could end up being a footnote that nobody cares about
not clear what will make the difference
Officlal website
http://www.webassembly.org
Official GitHub
https://github.com/WebAssembly
WABT: https://github.com/WebAssembly/wabt
Binaryen: https://github.com/WebAssembly/binaryen
Specs: https://github.com/WebAssembly/spec
Proposals: https://github.com/WebAssembly/proposals
MDN
https://developer.mozilla.org/en-US/docs/WebAssembly
more complete list at
https://github.com/appcypher/awesome-wasm-langs
Architect, Engineering Manager/Leader, "force multiplier"
http://www.newardassociates.com
http://blogs.newardassociates.com
Sr Distinguished Engineer, Capital One
Educative (http://educative.io) Author
Performance Management for Engineering Managers
Books
Developer Relations Activity Patterns (w/Woodruff, et al; APress, forthcoming)
Professional F# 2.0 (w/Erickson, et al; Wrox, 2010)
Effective Enterprise Java (Addison-Wesley, 2004)
SSCLI Essentials (w/Stutz, et al; OReilly, 2003)
Server-Based Java Programming (Manning, 2000)