Memory limits in webassembly

WebAssembly has a WebAssembly.Memory object and the binary has a memory section. Through these, a developer provides educated guesses about minimum and maximum memory usage, the VM then allocates at least the minimum (or fails). A developer can then, at runtime, ask for more through grow_memory which tools like Emscripten will use under the hood of malloc (it's somewhat similar to sbrk).

For asm.js it was difficult to know how the ArrayBuffer was going to be used, and on some 32-bit platforms you often ran into process fragmentation which made it hard to allocate enough contiguous space in the process' virtual memory (the ArrayBuffer must be contiguous in the browser process' virtual address space, otherwise you'd have a huge perf hit). You'd try to allocate 256MiB and sometimes hard-fail. This got extremely difficult if the browser wasn't multi-process, because all the other tabs are competing for 32 bits of virtual address space. Browsers were a bit silly a few years ago, they got better, but 32 bits ain't much to go around.

WebAssembly is backed by WebAssembly.Memory which is a special type of ArrayBuffer. This means that a WebAssembly implementation can be clever about that ArrayBuffer. On 32-bit there's not much to do: if you run out of contiguous address space then the VM can't do much. But on 64-bit platforms there's plenty of address space. The browser implementation can choose to prevent you from creating too many WebAssembly.Memory instances (allocating virtual memory is almost free, but not quite), but you should be able to get a few 4GiB allocations. Note that the browser will only allocate that space virtually, and commit physical addresses for the minimum number of pages you said you need. Afterwards it'll only allocate physically when you use grow_memory. That could fail (physical memory is about as abundant as the amount of RAM, give or take swap space), but it's much more predictable.

An implementation can pull a similar trick on 32-bit platforms (over-commit but keep PROT_NONE and not physically allocated), assuming fragmentation allows, but that's up to the implementation and how it think this affects ASLR. Realistically it's hard to find memory when there's not much to go around, but virtually and physically.

WebAssembly is currently specified as an ILP32 process: pointers are 32 bits. You're therefore hard-limited to 4GiB. We may add wasm64 in the future.


I summarize a bit the above answers, the comments and a bit more of googling done around; there are two issues that prevent using WebAssembly for being used projects that require a significant amount of memory:

  • current WebAssembly implementations follow a 32bit addressing space model, so no hope of using more than 4gb of mem until wasm64 is out (proposal overview).
  • browsers arbitrarily decide what is the amount of memory given to a page. This is (mostly) for security reason because people love to think to web pages as something more "safe" than desktop applications.

Hopefully both issues can be solved. I hope that browsers will expose those limits in a explicit way; just like when a page request to use your camera it is notified, you should simply notify the user that a page want a ton of memory and block it until you answer.