Skip to content
Alon Zakai edited this page Sep 23, 2015 · 13 revisions

Split memory is a compilation mode that splits the normal single typed array of memory into multiple chunks. It is a non-asm.js mode, enabled by building with -s SPLIT_MEMORY=N where N is the chunk size.

Benefits

Each chunk of memory is a separate allocation from the browser. That means that applications can use more memory, without worrying about issues with memory fragmentation. For example, 2GB of memory can often be allocated in this mode, while 1GB is otherwise often the limit.

Model

Each split chunk gets an independent malloc/free space, implemented by a dlmalloc mspace. That means we assume each malloc is provided by a single chunk, and therefore allocations cannot span chunks. It also means the chunk size must be big enough for the single largest allocation. (That includes filesystem allocations, so if you have large amounts of file data, you might want to run the file packager with --no-heap-copy to avoid a copy into the heap, or --lz4 to both compress the data and avoid the heap copy).

We implement HEAP*.subarray by returning a slice into the proper chunk. When an end offset is not provided, we slice to the end of the current chunk, relying on the fact that no allocation can span chunks. A runtime exception is thrown if an end offset is provided and it implies the slice would span more than 1 chunk.

Modifying non-compiled code

When this option is enabled, all heap accesses go through get32() etc methods, that access the proper slice for the pointer. We also fix up non-compiled code as well, modifying hand-written HEAP8[x] = 5 into set8(x, 5) and so forth, automatically. This is done on all the code that is seen at compile time, which includes all JS library code, --pre-js and --post-js, as well as EM_ASM code chunks.

However, code that we do not see at compile time cannot be fixed. If you have some external code in another script tag on the same page, you must make sure it uses the proper get*,set* methods if it accesses memory. Also, if you eval some code, as in emscripten_run_script, that is new code only seen at runtime.

Performance

Each memory access must first find the right slice of memory, which adds significant overhead. Also, this code generation mode is not asm.js-compatible. There is therefore a significant slowdown, around 3x on Firefox anad 6x on Chrome.