Skip to main content

Command Palette

Search for a command to run...

Understanding Web Assembly

Updated
3 min read
Understanding Web Assembly
T

Just a guy who loves to write code and watch anime.

The JavaScript Problem

JavaScript engines receive text and must parse it into something executable. The bigger issue is that JavaScript has no types. A variable can hold anything, and this can change at runtime.

V8 and other modern engines try to optimize by watching your running code. If a function always receives numbers, the engine compiles fast machine code assuming numbers. But if you pass a string instead, that optimized code is worthless. The engine deoptimizes, throws away the work, and starts over.

This speculation cycle runs constantly while your program executes. Even fast JavaScript requires massive ongoing effort from the engine.

What WebAssembly Actually Is

WebAssembly is binary bytecode with explicit types. Instead of text that needs parsing and speculation, you send instructions that already specify whether they operate on 32-bit integers, 64-bit floats, or other concrete types.

It's an abstract instruction set, not tied to any specific CPU architecture. Browsers know how to translate it to whatever machine code the user's processor needs.

How You Create It

Write code in C, C++, Rust, or similar languages. Use a compiler that targets WebAssembly instead of native platforms. Emscripten handles C/C++. Rust has built-in support.

Compilation produces a .wasm file containing typed bytecode. Every operation specifies its types. No ambiguity exists.

How It Gets To The Browser

The .wasm file lives on your server. JavaScript fetches it and uses the WebAssembly API to instantiate it. The browser validates the bytecode for safety, then compiles it to machine code for the local CPU. This compilation is fast because the bytecode maps cleanly to CPU instructions.

The Execution Model

WebAssembly runs with its own linear memory, essentially a byte array. Compiled code operates on this memory. JavaScript can access it as an ArrayBuffer for data sharing.

WebAssembly exports functions that JavaScript calls. When called, control passes to compiled machine code that executes directly on the CPU.

WebAssembly cannot touch the DOM or browser APIs. It only does computation. To interact with the browser, it calls JavaScript functions you provide during setup.

Why It's Fast

Types are known upfront. An i32 addition compiles straight to a CPU add instruction. No runtime type checking. No speculation that might fail.

Memory is a flat byte array with explicit pointers. No JavaScript object complexity, no property lookups, no prototype chains. Memory access translates directly to CPU operations.

The browser generates efficient machine code in one pass. No profiling phase, no tiered compilation, no deoptimization failures.

When To Use It

Use it for heavy computation: image processing, video encoding, physics engines, cryptography, scientific calculations.

Use it to port existing C++ or Rust codebases to the web without rewriting them.

Don't use it for normal web development. UI building, DOM manipulation, form handling, and API calls are better in JavaScript. Crossing the JavaScript/WebAssembly boundary has overhead.

The Complete Flow

Write C++ or Rust code. Compile to .wasm bytecode. Deploy it to your server.

Your webpage loads JavaScript that fetches the .wasm file. The browser compiles it to machine code and instantiates it. JavaScript calls exported WebAssembly functions for heavy computation. WebAssembly calls back to JavaScript for browser interaction. They share data through linear memory.

JavaScript handles application logic and the browser. WebAssembly handles expensive computation.

What This Means

WebAssembly lets you run languages other than JavaScript in browsers at near-native speed. The web becomes viable for applications that need serious computational performance.

It doesn't replace JavaScript. JavaScript handles the web platform and application logic. WebAssembly is a specialized tool for performance-critical computation.

The core difference: JavaScript optimizes for flexibility and pays a runtime cost. WebAssembly optimizes for predictability. The compiler decides everything ahead of time so the browser just executes efficiently.