WebAssembly Memory Alignment Requirements
This article explores the memory alignment requirements for reading and writing to WebAssembly (Wasm) linear memory. It covers how WebAssembly handles naturally aligned and misaligned memory accesses, the performance implications of alignment on different hardware, and how alignment is represented in Wasm binary instructions.
Natural Alignment in WebAssembly
In WebAssembly, memory operations are most efficient when they are “naturally aligned.” Natural alignment means that the memory address of a data value is a multiple of the size of the data type being accessed. WebAssembly supports several primitive data types, each with its own natural alignment requirement:
- 1-byte values (i8): Can be accessed at any byte address (1-byte aligned).
- 2-byte values (i16): Best accessed at addresses divisible by 2.
- 4-byte values (i32, f32): Best accessed at addresses divisible by 4.
- 8-byte values (i64, f64): Best accessed at addresses divisible by 8.
- 16-byte values (v128/SIMD): Best accessed at addresses divisible by 16.
How WebAssembly Handles Alignment
Every load and store instruction in the WebAssembly binary format includes an alignment attribute, encoded as a power of two. This attribute represents the expected alignment of the memory operation.
The alignment attribute acts as a hint to the WebAssembly runtime execution engine (such as V8, SpiderMonkey, or Wasmtime). It informs the compiler of the guarantee that the target address will be aligned to that boundary, allowing the engine to generate the most optimal machine code for the host CPU.
Misaligned Memory Accesses
WebAssembly does not enforce strict alignment at runtime. If a load or store instruction executes with an address that is not aligned to the natural boundary of the data type (or the alignment specified in the instruction), the operation will still succeed. WebAssembly guarantees that misaligned memory accesses are semantically valid and will not cause a trap (crash) or memory corruption.
However, misaligned accesses can come with a performance cost:
- Hardware Support: Modern x86 and x86_64 processors handle misaligned memory accesses in hardware with negligible performance loss, except when the access crosses a cache line boundary.
- Emulated Access: On some ARM processors or older architectures, misaligned memory access is not supported directly by the hardware. In these cases, the WebAssembly runtime or the underlying operating system must trap and emulate the access using multiple smaller, aligned instructions. This emulation can result in a significant performance penalty.
Developer Best Practices
Because WebAssembly is designed to run cross-platform, developers should always aim for natural alignment to ensure consistent performance across all devices.
When writing code in languages that compile to WebAssembly, such as C, C++, Rust, or Go, the compiler automatically handles data structure padding and alignment. However, when working with manual memory management, raw pointers, or custom serialization formats in WebAssembly linear memory, you must manually ensure that multi-byte values are read from and written to offsets that match their natural alignment.