SalakCode SalakCode
Browser APIs

WebAssembly

Run high-performance code in the browser

Advanced
browser wasm performance native

Definition

WebAssembly (Wasm) is a binary instruction format that enables high-performance applications to run in web browsers. It allows code written in languages like C, C++, and Rust to execute at near-native speed, making it ideal for compute-intensive tasks like video editing, gaming, CAD, and image processing.

What is WebAssembly?

Key Characteristics

WebAssembly has several defining characteristics: binary format (not text-based like JavaScript), stack-based virtual machine, linear memory model, portable across all modern browsers, and secure sandboxed execution environment.

Performance Comparison

Typical speedups include 10x to 20x faster for compute-heavy algorithms, 2x to 5x for general operations, and near-native performance for SIMD operations.

Basic Usage

Loading a WebAssembly Module

// Fetch and instantiate WASM
async function loadWasm() {
  const response = await fetch('./module.wasm');
  const bytes = await response.arrayBuffer();

  // Instantiate with JavaScript imports
  const { instance } = await WebAssembly.instantiate(bytes, {
    env: {
      memory: new WebAssembly.Memory({ initial: 256 }),
      table: new WebAssembly.Table({ initial: 0, element: 'anyfunc' }),
      consoleLog: (value) => console.log(value)
    }
  });

  return instance.exports;
}

// Usage
const wasm = await loadWasm();
const result = wasm.add(5, 3);
console.log(result);

Using wasm-bindgen (Rust)

// Rust code (lib.rs)
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn fibonacci(n: u32) -> u32 {
    if n == 0 { return 0; }
    if n == 1 { return 1; }
    fibonacci(n.wrapping_sub(1)).wrapping_add(fibonacci(n.wrapping_sub(2)))
}
// JavaScript usage
import { fibonacci } from './pkg';

console.log(fibonacci(40));

Use Cases

1. Image/Video Processing

// Real-time image filters
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const imageData = ctx.getImageData(0, 0, width, height);

// Pass to WASM for processing
const processed = wasm.applyFilter(
  imageData.data,
  imageData.width,
  imageData.height,
  'blur'
);

ctx.putImageData(processed, 0, 0);

2. Gaming

// Game engine compiled to WASM
const game = await loadGame();

// Main loop
function gameLoop() {
  wasm.update();
  wasm.render();
  requestAnimationFrame(gameLoop);
}

3. Cryptography

// Fast hashing
async function hashFile(file) {
  const arrayBuffer = await file.arrayBuffer();
  const hash = wasm.sha256(new Uint8Array(arrayBuffer));
  return hash;
}

4. Audio Processing

// Web Audio API + WebAssembly
const audioContext = new AudioContext();
const processor = audioContext.createScriptProcessor(4096, 1, 1);

processor.onaudioprocess = (e) => {
  const inputData = e.inputBuffer.getChannelData(0);
  const outputData = e.outputBuffer.getChannelData(0);
  wasm.processAudio(inputData, outputData, inputData.length);
};

Memory Management

Shared Linear Memory

// Create memory that both JS and WASM can access
const memory = new WebAssembly.Memory({
  initial: 256, // Pages (64KB each)
  maximum: 512,
  shared: true   // For multi-threading
});

// Access from JavaScript
const array = new Uint8Array(memory.buffer);
array[0] = 42;

// Access from WASM returns 42 at index 0

Passing Strings

// Helper functions for string conversion
function stringToPtr(str, wasm) {
  const encoder = new TextEncoder();
  const bytes = encoder.encode(str);
  const ptr = wasm.alloc(bytes.length + 1);

  const memory = new Uint8Array(wasm.memory.buffer);
  memory.set(bytes, ptr);
  memory[ptr + bytes.length] = 0; // Null terminator

  return ptr;
}

function ptrToString(ptr, wasm) {
  const memory = new Uint8Array(wasm.memory.buffer);
  let end = ptr;
  while (memory[end] !== 0) end++;

  const bytes = memory.slice(ptr, end);
  return new TextDecoder().decode(bytes);
}

SIMD (Single Instruction, Multiple Data)

Vector Operations

// 128-bit SIMD operations process 4 floats or 16 bytes at once

// Image processing example
function processPixelsSimd(data) {
  const result = wasm.processSimd(data);
  // Approximately 4x faster than scalar operations
  return result;
}

Debugging

Source Maps

Compile with debug info using emcc -g4 source.c -o output.js

In DevTools you can see original C/C++ code, set breakpoints, and inspect variables.

Error Handling

try {
  const result = wasm.riskyOperation();
} catch (e) {
  if (e instanceof WebAssembly.RuntimeError) {
    console.error('WASM Runtime Error:', e.message);
  }
}

Best Practices

1. Optimize JavaScript/WASM Calls

// Avoid: Many small calls
for (let i = 0; i < 1000; i++) {
  wasm.processOne(data[i]);
}

// Prefer: Batch operations
wasm.processMany(data, data.length);

2. Avoid Frequent Memory Resizing

// Pre-allocate sufficient memory
const memory = new WebAssembly.Memory({
  initial: 256,
  maximum: 256  // Fixed size
});

3. Use Workers for Heavy Computation

// main.js
const worker = new Worker('wasm-worker.js');
worker.postMessage({ imageData, filter: 'blur' });

worker.onmessage = (e) => {
  displayResult(e.data);
};
// wasm-worker.js
importScripts('./module.js');

self.onmessage = async (e) => {
  const wasm = await loadWasm();
  const result = wasm.processImage(e.data.imageData);
  self.postMessage(result);
};

Tools and Frameworks

Emscripten

Compile C/C++ to WASM:

emcc main.cpp -o index.html -s WASM=1 -s EXPORTED_FUNCTIONS='["_main","_calculate"]'

AssemblyScript

// TypeScript-like syntax
export function add(a: i32, b: i32): i32 {
  return a + b;
}
// Compiles to WebAssembly

Rust + wasm-pack

Build Rust for web:

wasm-pack build --target web

Generates: pkg/package.json, pkg/module_bg.wasm, pkg/module.js (bindings)

Key Takeaway

WebAssembly enables near-native performance in browsers for compute-intensive tasks. Use it for image processing, games, cryptography, and audio/video manipulation. Minimize JS-WASM boundary crossings, manage memory carefully, and consider Web Workers for heavy computations. Modern tools like wasm-pack and Emscripten make integration straightforward.

Resources

Related Topics