Web Assembly: What is it? Does it do things? Let's find out!

Watch Video

The following is the source code for this PDF.

Have any observations, criticisms, or corrections? Feel free to email me. Have a nice day!

% !TEX program = XeLaTeX
\documentclass[aspectratio=169]{beamer}
\mode<presentation>

\usepackage{tikz}
\usepackage{pgfpages} % notes
\usepackage{graphicx}
\usepackage{color} % for syntax highlighting definitions
\usepackage{fontspec} % for custom firacode setup
\usepackage{listings} % for formatting codeblocks
\usepackage[T1]{fontenc}

\usetheme{AnnArbor}
\usecolortheme{spruce}
\usecolortheme{rose}

\setbeamertemplate{navigation symbols}{}
\setbeamertemplate{enumerate items}[default]
\setbeamercolor{item projected}{bg=green!40!black,fg=white}
\setbeamercolor{section in toc}{fg=black}
%\setbeameroption{show notes on second screen}


%% code syntax highlighting
\definecolor{lightgray}{rgb}{.9,.9,.9}
\definecolor{darkgray}{rgb}{.4,.4,.4}
\definecolor{purple}{rgb}{0.65, 0.12, 0.82}
\definecolor{gruv-red}{RGB}{204,36,29}
\definecolor{gruv-yellow}{RGB}{215,153,33}
\definecolor{gruv-aqua}{RGB}{104,157,106}
\definecolor{gruv-green}{RGB}{69,133,136}

\lstdefinelanguage{JavaScript}{
  keywords={break, case, then, catch, continue, debugger, default, delete, do, else, false, finally, for, function, if, in, instanceof, new, null, return, switch, this, throw, true, try, typeof, var, void, while, with},
  morecomment=[l]{//},
  morecomment=[s]{/*}{*/},
  morestring=[b]',
  morestring=[b]",
  ndkeywords={class, export, boolean, throw, implements, import, this},
  keywordstyle=\color{gruv-green}\ttfamily,
  ndkeywordstyle=\color{darkgray}\ttfamily,
  identifierstyle=\color{black}\ttfamily,
  stringstyle=\color{darkgray}\ttfamily,
  frame=none,
  sensitive=true
}
\lstdefinelanguage{Rust}{
  keywordstyle=\color{gruv-yellow}\ttfamily,
  keywordstyle=[1]{\color{gruv-aqua}\ttfamily},
  keywordstyle=[2]{\color{gruv-yellow}\ttfamily},
  keywordstyle=[3]{\color{gruv-red}\ttfamily},
  morestring=[b]",
  morestring=[b]',
  stringstyle=\color{gray}\ttfamily,
  otherkeywords = {\&Display, \&str, \#\[wasm\_bindgen\]},
  morekeywords=[1]{derive, \#\[wasm\_bindgen\], wasm\_bindgen, js\_namespace, console},
  morekeywords=[2]{Serialize, KoreanInteger, Deserialize, String, i128, i32, char, \&str, \&Display},
  morekeywords=[3]{use, pub, fn, extern, struct, self, impl},
  frame=none,
  sensitive=true
}
\lstdefinelanguage{WASM}{
  keywords=[1]{module, type, func, table, memory, export, param, result},
  keywordstyle=\color{gruv-green}\ttfamily,
  frame=none,
  sensitive=true
}

\lstset{%
  basicstyle  = \fontfamily{pcr}\fontsize{10pt}{12pt}\selectfont,
  numberstyle = \small,
  numbersep   = 10pt,
  frame=none,
}

%% behavior modifications

\newenvironment{wideitemize}{\itemize\addtolength{\itemsep}{10pt}}{\enditemize}
\AtBeginSection[]
{
    \begin{frame}
        \frametitle{Journey}
        \tableofcontents[currentsection]
    \end{frame}
}

%% metadata

\title[WASM!]{Web Assembly: What does it do? Does it do things? Let's find out!}
\author[]{Andrew Zah \texttt{<zah@andrewzah.com>}}
\institute[Rust Meetup Seoul]{Rust Meetup Seoul}
\date{May 28, 2019}

%% preamble over

\begin{document}
\maketitle

\section*{Journey}
\begin{frame}
  \tableofcontents
\end{frame}

%%%%%%%%%%%%%%%%%%%

\section{What is WASM?}
\begin{frame}
  \frametitle{Web Assembly's Definition}
  \begin{block}{from webassembly.org (emphasis mine)}
    WebAssembly (abbreviated Wasm) is a \alert{binary instruction format} for a \alert{stack-based virtual machine}. Wasm is designed as a \alert{portable target} for compilation of high-level languages like C/C++/Rust, enabling \alert{deployment on the web} for client and server applications.
  \end{block}
\end{frame}

\begin{frame}
  \frametitle{What WASM is not}
  \begin{wideitemize}
    \item WASM is not a programming language, though you can write by hand
    \item<2-> WASM isn't standalone: it needs a host
    \item<3-> WASM is not intended to replace javascript
  \end{wideitemize}
\end{frame}

\begin{frame}
  \frametitle{what is it actually, though?}
  \begin{wideitemize}
    \item WASM's format isn't coupled to any OS or architecture
    \item<2-> Very similar to Java's bytecode or C\#'s CLR
    \item<3-> Name and definition is a misnomer
    \item<4-> It can run \alert{anywhere} you can build a \alert{host}
  \end{wideitemize}
\end{frame}

\begin{frame}
  \frametitle{WASM's specification}
  \begin{wideitemize}
    \item WASM is \alert{stack-based}, not register-based
    \item<2-> WASM 1.0 only has 4 primitives
    \item<3-> `i32`, `i64`, `f32`, `f64` 
    \item<4-> No arrays
    \item<5-> no \alert{jmp} instruction
  \end{wideitemize}
  \note[item]{Forth and retro are just about the only somewhat-mainline language that are stack-based.}
  \note[item]{RPL also exists but\ldots}
\end{frame}

\begin{frame}
  \frametitle{memory}
  \begin{columns}
    \begin{column}{0.5\textwidth}
      \begin{wideitemize}
        \item WASM has no \alert{new::()} operator or \alert{heap}
        \item<2-> There are no objects or or garbage collection
        \item<3-> Instead, WASM has \alert{linear memory}
        \item<4-> this causes a need for linearization and bitmasking, etc
      \end{wideitemize}
    \end{column}
    \begin{column}{0.5\textwidth}
      \begin{center}
        \uncover<3-> {
          \begin{tikzpicture}
            \draw [gray] (0,0) rectangle (4,1) node[pos=.5] {unused};
            \draw [teal] (0,1) rectangle (4,2) node[pos=.5] {var3 [80\ldots119]};
            \draw [gray] (0,2) rectangle (4,3) node[pos=.5] {var2 [40\ldots79]};
            \draw [teal] (0,3) rectangle (4,4) node[pos=.5] {var1 [0\ldots39]};
          \end{tikzpicture}
        }
      \end{center}
    \end{column}
  \end{columns}
\end{frame}

\begin{frame}
  \frametitle{anyone can be a WASM host!}
  
  \begin{alertblock}{The Host needs to:}
    \begin{enumerate}
      \item Load and validate the WASM binary (the file, not the logic)
      \item<2-> Expose Exports
      \item<3-> Satisfy Imports
      \item<4-> Interpret \& Execute Modules
      \item<5-> Isolate Modules
    \end{enumerate}
  \end{alertblock}
\end{frame}

\begin{frame}
  \frametitle{infinity and beyond?}
  \begin{wideitemize}
    \item WebAssembly modules are hotswappable
    \item<2-> PLCs (Programmable Logic Controllers) could adhere to a well-known contract
    \item<2-> This would let us program for hardware controllers in \alert{any language}!
    \item<3-> \alert{wasmi} is an rust open-source wasm interpreter
    \item<4-> \alert{serverless-wasm} does indeed exist
  \end{wideitemize}
\end{frame}

\begin{frame}
  \frametitle{security}
  \begin{wideitemize}
    \item WASM binaries can always be converted back to plaintext
    \item<2-> Do not put secrets in WASM modules
    \item<3-> \alert{Message handoffs} are not always secure!
    \item<4-> Accordingly, \alert{sign} and \alert{encrypt} modules!
  \end{wideitemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{add example: rust side}
  \begin{block}{main.rs}
    \begin{lstlisting}[language=rust]
#[no_mangle]
pub extern "C" fn add_one(x: i32) -> i32 {
    x + 1
}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]
  \frametitle{add example: generated WASM}
  \begin{block}{main.wasm}
    \begin{lstlisting}[language=wasm]
(module
  (type $t0 (func (param i32) (result i32)))
  (func $add_one
      (export "add_one") (type $t0) (param $p0 i32) (result i32)
    get_local $p0
    i32.const 1
    i32.add)
  (table $T0 1 1 anyfunc)
  (memory $memory (export "memory") 17))
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}
  \frametitle{summary}
  \begin{wideitemize}
    \item WASM is simply a instruction format that's portable
    \item WASM can run anywhere so long as a host exists
    \item Just because you can write WASM doesn't mean you should
  \end{wideitemize}
\end{frame}

%%%%%%%%%%%%%%%%%%%

\section{Applications of WASM in Rust}

\begin{frame}
  \frametitle{wasm-bindgen}
  \begin{wideitemize}
    \item CLI tool to generate bindings for the wasm code to work
    \item<2-> can be run manually but \alert{wasm-pack} simplifies things
    \item<3-> \alert{automates} linearization, strings, complex types bindings
  \end{wideitemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{configuring cargo}
  \begin{block}{Cargo.toml}
    \begin{lstlisting}
[lib]
crate-type = ["cdylib"]

[build]
target = "wasm32-unknown-unknown"

[dependencies]
wasm-bindgen = "0.2.45"

[dependencies.rand]
features = ["wasm-bindgen"]
\end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]
  \frametitle{rust wasm:  functions}
  \begin{block}{main.rs}
    \begin{lstlisting}[language=rust]
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern "C" {
    #[wasm_bindgen(js_namespace = console)]
    fn log(s: &str);
    #[wasm_bindgen(method, structural, js_namespace = ROT)]
    fn draw(this: &Display, x: i32, y: i32, ch: &str);
}

#[wasm_bindgen]
pub fn greet(name: &str) {
    log(&format!("Hello, {}!", name));
}
\end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]
  \frametitle{js\_sys and web\_sys provide bindings}
  \begin{block}{main.rs}
    \begin{lstlisting}[language=rust]
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsValue;
use web_sys::console::log_1;

#[wasm_bindgen]
pub fn hi() {
  log_1(JsValue::from_str("hi"));
}
\end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]
  \frametitle{rust wasm: structs and impls}
  \begin{block}{main.rs}
    \begin{lstlisting}[language=rust]
#[wasm_bindgen]
pub struct Counter { count: i32, }

#[wasm_bindgen]
impl Counter {
  pub fn get(&self) -> char {
    log(format!("Count: {}", self.count));
    self.count
  }
}
    \end{lstlisting}
  \end{block}
\end{frame}


\begin{frame}
  \frametitle{wasm-pack}
  \begin{wideitemize}
    \item<1-> higher level wrapper for \alert{wasm-bindgen}
    \item<2-> commands: \alert{build}, \alert{test}, \alert{pack}, \alert{publish}, \alert{login}
    \item<3-> \alert{wasm-bindgen} is still a dependency
  \end{wideitemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{wasm-pack output in /pkg}
  \begin{block}{exa -T -L1 pkg/}
    \begin{lstlisting}
pkg/
  package.json
  wasm_pack_test.d.ts
  wasm_pack_test.js
  wasm_pack_test_bg.d.ts
  wasm_pack_test_bg.wasm
\end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]
  \frametitle{wasm-pack output}
  \begin{block}{main.js}
    \begin{lstlisting}[language=javascript]
const wasm = import('./pkg/hello_world');

wasm
  .then(m => m.greet('World!'))
  .catch(console.error);
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}
  \frametitle{extensions and alternatives}
  \begin{wideitemize}
    \item \alert{web-sys} and \alert{js-sys} provide raw js/web API bindings
    \item<2-> \alert{std-web} has a similar goal but provides more JS interop + APIs
    \item<3-> \alert{rust-neon} (external tool) generates \alert{Node.js} modules
    \item<4-> \alert{yew} is a web framework that compiles to WASM
  \end{wideitemize}
\end{frame}

\begin{frame}
  \frametitle{optimizing the WASM output}
  \begin{columns}
    \begin{column}{0.6\textwidth}
      \begin{wideitemize}
        \item \alert{wasm-opt} can significantly reduce binary size 
        \item<2-> \alert{wasm2wat} can be used to confirm
        \item<3-> \alert{twiggy} is a wasm profiler that analyzes call graphs
        \item<4-> set \alert{lto = true} in Cargo.toml, but limit to release only
      \end{wideitemize}
    \end{column}
    \begin{column}{0.4\textwidth}
      \uncover<3->{
        \includegraphics[scale=0.34]{twiggy.png}
      }
    \end{column}
  \end{columns}
\end{frame}

%%%%%%%%%%%%%%%%%%%

\section{A Real, Non-Trivial WASM App}
\begin{frame}
  \frametitle{korean apps}
  \begin{wideitemize}
    \item Initially I wrote a cargo crate, \alert{korean-numbers}
    \item<2-> I wanted a way to use this logic in a webapp with React
    \item<3-> I went with \alert{wasm-bindgen} calls in \alert{package.json} scripts
  \end{wideitemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{project structure}
  \begin{block}{exa -T -L2 .}
    \begin{lstlisting}
dist/
frontend/
native/
node_modules/
package.json
webpack.config.js
yarn.lock
\end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]
  \frametitle{why wasm-pack may be better}
  \begin{block}{package.json}
  \begin{lstlisting}
"scripts": {
  "build-debug": "cd native; cargo +nightly build
      --target wasm32-unknown-unknown
    && wasm-bindgen
        target/wasm32-unknown-unknown/debug/korean_wasm.wasm
      --out-dir ../frontend/wasm; cd .."
}
\end{lstlisting}
\end{block}
\end{frame}

\begin{frame}[fragile]
  \frametitle{rust side: glue code}
  \begin{block}{native/src/lib.rs}
    \begin{lstlisting}[language=rust]
use korean_nums::{ NumberSystem, ...}
#[wasm_bindgen]
struct KoreanInteger { number: i128, hangeul: String, }

#[wasm_bindgen]
pub fn random_korean_int(
  lower_str: &str, upper_str: &str, num_system: &str)
  -> KoreanInteger
{ ... }
\end{lstlisting}
\end{block}
\end{frame}

\begin{frame}[fragile]
  \frametitle{frontend layout}
  \begin{block}{exa -T -L2 frontend/}
  \begin{lstlisting}
components/
  korean_numbers/
index.html
index.js
wasm/
  korean_wasm.d.ts
  korean_wasm.js
  korean_wasm_bg.d.ts
  korean_wasm_bg.wasm
\end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]
  \frametitle{calling code from the frontend}
  \begin{block}{frontend/components/korean\_numbers/index.js}
    \begin{lstlisting}[language=javascript]
const { random_int } = require("../../wasm/korean_wasm");

const res = random_korean_int(0, 10, "sino");
\end{lstlisting}
\end{block}
\end{frame}

\begin{frame}[fragile]
  \frametitle{non-trivial optimizations}
  \begin{columns}
    \begin{column}{0.45\textwidth}
      \begin{block}{ls -lah | rg wasm | awk `{print \$5, \$9}' | sort}
        \begin{lstlisting}
282K wasm-opt-Oz-flag.wasm
283K wasm-opt-Os-flag.wasm
306K wasm-opt-O3-flag.wasm
573K wasm-opt-default.wasm
695K bindgen-development.wasm
\end{lstlisting}
    \end{block}
    \end{column}
    \begin{column}{0.45\textwidth}<2->
      \begin{block}{release mode versions}
        \begin{lstlisting}
126K wasm-opt-lto-Oz-flag.wasm
136K bindgen-release-lto.wasm
166K bindgen-release.wasm
\end{lstlisting}
    \end{block}
    \end{column}
  \end{columns}
\end{frame}

\begin{frame}[fragile]
  \frametitle{inspecting with twiggy}
  \begin{block}{twiggy top wasm-bindgen-default.wasm}
\begin{lstlisting}
Shallow Bytes │ Shallow % │ Item
124493 | 17.50% | "function names" subsection
57598  |  8.10% | rand_hc::hc128::Hc128Core::sixteen_steps
50394  |  7.09% | <rand_hc::hc128::Hc128Core>...::generate
24781  |  3.48% | data[1]
22978  |  3.23% | data[2]
 7624  |  1.07% | <rand::rngs::entropy::EntropyRng>...::try_fill_bytes
 6928  |  0.97% | korean_nums::parse::parse_hangeul_sino
 4918  |  0.69% | core::num::flt2dec::strategy::dragon::mul_pow10
\end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]
  \frametitle{inspecting release mode with twiggy}
  \begin{block}{twiggy top wasm-opt-Oz-release-lto.wasm}
\begin{lstlisting}
Shallow Bytes │ Shallow % │ Item
9753 | 7.55% | data[0]
8556 | 6.62% | code[33]
8457 | 6.54% | data[1]
7012 | 5.42% | code[76]
6156 | 4.76% | code[127]
6145 | 4.75% | code[75]
\end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}
  \begin{center}
    {\huge Thank you} \\
    Andrew Zah
  \end{center}
\end{frame}

%%%%%%%%%%%%%%%%%%%

\section*{Appendix}
\begin{frame}[plain]
  \includegraphics[scale=0.34]{webassembly-studio.png}
\end{frame}

\begin{frame}
  \frametitle{further reading}
  \begin{itemize}
    \item \alert{WASM Homepage} \texttt{https://webassembly.org}
    \item \alert{WASM Spec} \texttt{https://webassembly.github.io/spec/}
    \item \alert{wasm-bindgen docs} \texttt{https://rustwasm.github.io/docs/wasm-bindgen/}
    \item \alert{stdweb} \texttt{https://github.com/koute/stdweb}
    \item \alert{twiggy profiler} \texttt{https://github.com/rustwasm/twiggy}
    \item \alert{wat2wasm, wasm2wat, and more} \texttt{https://github.com/WebAssembly/wabt}
    \item \alert{websys} \texttt{https://rustwasm.github.io/wasm-bindgen/api/web\_sys/}
    \item \alert{neon-bindings} \texttt{https://github.com/neon-bindings/neon}
    \item \alert{optimizing emscriptem} \texttt{https://emscripten.org/docs/optimizing/Optimizing-Code.html}
    \item \alert{wasmi: rust wasm interpreter} \texttt{https://github.com/paritytech/wasmi}
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{bibliography}
  \begin{thebibliography}{Dijkstra, 1982}
    \bibitem[Hoffman, 2019]{Hoffman2019}
      K.~Hoffman.
      \newblock{\em Programming WebAssembly with Rust \\
        \small Unified Development for Web, Mobile, and Embedded Applications }
      \newblock{The Pragmatic Programmers, LLC}
      \newblock{ISBN-13: 978-1-68050-636-5}
  \end{thebibliography}
\end{frame}

\end{document}

Random quote


Tags: Rust | Webassembly
Categories: Talks