What is WebAssembly Linear Memory?
In traditional programming (like C or C++ compiled for a native OS), applications request memory from the operating system via malloc, which manages a complex, heavily abstracted virtual memory space. WebAssembly (Wasm) does not have access to the host's operating system.
Instead, Wasm utilizes Linear Memory. To a WebAssembly module, memory is simply a single, contiguous array of raw bytes (like a giant JavaScript ArrayBuffer or SharedArrayBuffer). The module can read and write to this array using simple integer memory addresses. It is completely isolated (sandboxed) from the host browser or OS memory, ensuring strict security.
Why are Wasm Pages exactly 64KB?
WebAssembly memory cannot be allocated byte-by-byte. It must be allocated in strictly sized chunks called Pages. Every standard Wasm page is exactly 65,536 bytes (64 Kilobytes).
Why 64KB? Most native operating systems (Linux, Windows) allocate memory in 4KB pages. The Wasm specification authors deliberately chose 64KB to ensure cross-platform compatibility and performance:
- 64KB is a multiple of almost all native OS page sizes (4KB, 16KB, 64KB), meaning the Wasm runtime (V8, SpiderMonkey, Wasmtime) can cleanly map Wasm pages directly to native OS pages using
mmapwithout awkward boundaries. - It reduces the overhead of bounds-checking in the JavaScript engine.
- If a Wasm module needs 1MB of memory, it only needs to track 16 pages, rather than 256 OS-level pages.
WebAssembly Primitive Data Types
Because WebAssembly is a low-level target language, it only natively understands a few fundamental numeric types. If you are calculating how much linear memory you need for an array, you must calculate based on these types:
- i32 & f32 (4 Bytes): 32-bit integers and floating-point numbers. A single 64KB page can hold exactly 16,384 of these values.
- i64 & f64 (8 Bytes): 64-bit integers and floating-point numbers. A single 64KB page holds 8,192.
- v128 (16 Bytes): 128-bit vectors used for SIMD (Single Instruction, Multiple Data) parallel processing operations. A single 64KB page holds 4,096.
Hexadecimal Addressing & Pointers
Inside a wasm32 module, pointers are simply 32-bit integers representing an exact byte offset from the start of the linear memory array (index 0). For example, allocating 16 pages (1MB) creates a memory block spanning from address 0x00000000 to 0x000FFFFF.
Attempting to read or write to an address beyond the allocated boundary (e.g., trying to access 0x00100000 in a 1MB block) triggers an immediate out-of-bounds Memory Access Trap, terminating execution to preserve sandbox security.
Allocator Overhead (wee_alloc & dlmalloc)
Raw linear memory is completely unmanaged. There is no built-in Garbage Collector or malloc implementation in the WebAssembly specification. If you compile C or Rust to Wasm, the compiler must actually inject a memory allocator (like dlmalloc for C, or wee_alloc for Rust) directly into your `.wasm` binary.
These allocators sit inside the linear memory and consume a portion of it to keep track of pointers, object headers, and free lists. When calculating memory requirements for a heavy application, you must assume a 5% to 10% overhead loss to the allocator metadata.
The 4GB wasm32 Limit & wasm64
Because wasm32 utilizes 32-bit pointers, a module can physically never address a byte beyond the 4GB mark (65,536 pages). If your application attempts to call memory.grow past this point, it will fail.
To solve this for enterprise workloads (databases, AI models), the Wasm governing body is finalizing the wasm64 proposal. wasm64 upgrades pointers to 64-bit integers, effectively expanding the memory limit to 16 Exabytes. Currently, wasm64 is highly experimental and requires explicit flags to enable in Chrome and Node.js.