What is WebAssembly
WebAssembly (WASM) is a binary instruction format that can be executed in browsers. It can be compiled from languages like C/C++, Rust, and Go, executing native-like code with near-JavaScript performance.
flowchart LR
subgraph Source["Source Code"]
Rust["Rust"]
CPP["C/C++"]
Go["Go"]
end
subgraph Compile["Compile"]
WASM[".wasm binary"]
end
subgraph Runtime["Runtime"]
Browser["Browser Runtime"]
JS["JavaScript invocation"]
end
Rust -->|"LLVM"| WASM
CPP -->|"LLVM"| WASM
Go --> WASM
WASM --> Browser
Browser --> JS
Features:
- Near-native execution speed
- Language agnostic (multi-language support)
- Sandboxed, secure execution
- JavaScript interoperability
- Streaming compilation support
Performance Comparison
Matrix Multiplication (1000x1000):
| Implementation | Time |
|---|---|
| JavaScript | 2,500ms |
| WASM (Rust) | 850ms |
| Native | 700ms |
Image Processing (1920x1080):
| Implementation | Time |
|---|---|
| JavaScript | 180ms |
| WASM | 72ms |
Encryption (AES-256):
| Implementation | Time |
|---|---|
| JavaScript | 320ms |
| WASM | 125ms |
Note: JS engine JIT optimization may reduce the gap
Rust + WebAssembly
Setup
# Install wasm-pack
cargo install wasm-pack
# Create project
cargo new --lib wasm-example
cd wasm-example
# Cargo.toml
[package]
name = "wasm-example"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies]
wasm-bindgen = "0.2"
js-sys = "0.3"
web-sys = { version = "0.3", features = ["console"] }
[profile.release]
opt-level = "z" # Size optimization
lto = true # Link-time optimization
Rust Implementation
// src/lib.rs
use wasm_bindgen::prelude::*;
// Function callable from JavaScript
#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
// Function handling strings
#[wasm_bindgen]
pub fn greet(name: &str) -> String {
format!("Hello, {}!", name)
}
// Exporting a struct
#[wasm_bindgen]
pub struct Calculator {
value: f64,
}
#[wasm_bindgen]
impl Calculator {
#[wasm_bindgen(constructor)]
pub fn new() -> Calculator {
Calculator { value: 0.0 }
}
pub fn add(&mut self, x: f64) {
self.value += x;
}
pub fn subtract(&mut self, x: f64) {
self.value -= x;
}
pub fn multiply(&mut self, x: f64) {
self.value *= x;
}
pub fn divide(&mut self, x: f64) -> Result<(), JsValue> {
if x == 0.0 {
return Err(JsValue::from_str("Division by zero"));
}
self.value /= x;
Ok(())
}
pub fn get_value(&self) -> f64 {
self.value
}
pub fn reset(&mut self) {
self.value = 0.0;
}
}
// Array processing
#[wasm_bindgen]
pub fn sum_array(arr: &[i32]) -> i32 {
arr.iter().sum()
}
// Using JS console
#[wasm_bindgen]
pub fn log_to_console(message: &str) {
web_sys::console::log_1(&message.into());
}
// Fast image processing example
#[wasm_bindgen]
pub fn apply_grayscale(data: &mut [u8]) {
for chunk in data.chunks_exact_mut(4) {
let r = chunk[0] as f32;
let g = chunk[1] as f32;
let b = chunk[2] as f32;
// ITU-R BT.601 coefficients
let gray = (0.299 * r + 0.587 * g + 0.114 * b) as u8;
chunk[0] = gray;
chunk[1] = gray;
chunk[2] = gray;
// chunk[3] (alpha) remains unchanged
}
}
// Fibonacci sequence (for benchmarking)
#[wasm_bindgen]
pub fn fibonacci(n: u32) -> u64 {
if n <= 1 {
return n as u64;
}
let mut a: u64 = 0;
let mut b: u64 = 1;
for _ in 2..=n {
let temp = a + b;
a = b;
b = temp;
}
b
}
Build and Usage
# Build
wasm-pack build --target web --release
// JavaScript/TypeScript usage
import init, {
add,
greet,
Calculator,
sum_array,
apply_grayscale,
fibonacci
} from './pkg/wasm_example.js';
async function main() {
// Initialize WASM module
await init();
// Basic function call
console.log(add(2, 3)); // 5
console.log(greet('World')); // "Hello, World!"
// Class usage
const calc = new Calculator();
calc.add(10);
calc.multiply(2);
console.log(calc.get_value()); // 20
// Array processing
const arr = new Int32Array([1, 2, 3, 4, 5]);
console.log(sum_array(arr)); // 15
// Image processing
const canvas = document.getElementById('canvas') as HTMLCanvasElement;
const ctx = canvas.getContext('2d')!;
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
apply_grayscale(imageData.data);
ctx.putImageData(imageData, 0, 0);
// Performance measurement
console.time('WASM Fibonacci');
fibonacci(40);
console.timeEnd('WASM Fibonacci');
}
main();
Practical Use Cases
| Category | Examples |
|---|---|
| Image/Video Processing | Figma (design tool), Squoosh (image compression), FFmpeg.wasm (video conversion) |
| Games/3D | Unity WebGL, Unreal Engine, Godot Engine |
| Development Tools | VS Code (Monaco Editor), Pyodide (Python in browser), SQLite WASM |
| Cryptography/Security | 1Password (password manager), Signal (encrypted chat), Hash computation |
Size Optimization
# For Rust
# Optimization with wasm-opt
wasm-opt -Oz input.wasm -o output.wasm
# Compression
gzip -9 output.wasm
# Brotli compression (more efficient)
brotli -9 output.wasm
# Cargo.toml optimization settings
[profile.release]
opt-level = "z" # Size-prioritized optimization
lto = true # Link-time optimization
codegen-units = 1 # Code generation units to 1
panic = "abort" # Abort on panic
strip = true # Remove symbol information
Browser Support
| Browser | Support |
|---|---|
| Chrome | 57+ (2017~) |
| Firefox | 52+ (2017~) |
| Safari | 11+ (2017~) |
| Edge | 16+ (2017~) |
| Node.js | 8+ (2017~) |