Introduction to WebAssembly - High-Speed Binary Format for Browsers

2025.12.02

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):

ImplementationTime
JavaScript2,500ms
WASM (Rust)850ms
Native700ms

Image Processing (1920x1080):

ImplementationTime
JavaScript180ms
WASM72ms

Encryption (AES-256):

ImplementationTime
JavaScript320ms
WASM125ms

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

CategoryExamples
Image/Video ProcessingFigma (design tool), Squoosh (image compression), FFmpeg.wasm (video conversion)
Games/3DUnity WebGL, Unreal Engine, Godot Engine
Development ToolsVS Code (Monaco Editor), Pyodide (Python in browser), SQLite WASM
Cryptography/Security1Password (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

BrowserSupport
Chrome57+ (2017~)
Firefox52+ (2017~)
Safari11+ (2017~)
Edge16+ (2017~)
Node.js8+ (2017~)
← Back to list