|
| 1 | +Memory usage estimation for a module |
| 2 | +==================================== |
| 3 | + |
| 4 | +This document aims to provide information useful to make a rough estimation |
| 5 | +of necessary memory to execute a WASM module. |
| 6 | + |
| 7 | +Instead of trying to cover every possible configurations, |
| 8 | +the following configuration is assumed in this document: |
| 9 | + |
| 10 | +* Module is built with `wasi-sdk` |
| 11 | +* Module is loaded with `wasm_runtime_load` |
| 12 | +* AOT is used |
| 13 | +* WASI is used |
| 14 | +* libc heap is used |
| 15 | +* app heap is not used |
| 16 | +* The pthread implementation in `wasi-libc`, which is based on `wasi-threads` |
| 17 | + (`WASM_ENABLE_LIB_WASI_THREADS`, which is not available on `main` branch |
| 18 | + yet) might be used |
| 19 | +* The another pthread implementation (`WASM_ENABLE_LIB_PTHREAD`) is not used |
| 20 | + |
| 21 | +Module |
| 22 | +------ |
| 23 | + |
| 24 | +The memory to store the module binary is allocated by the embedder and |
| 25 | +passed to `wasm_runtime_load`. |
| 26 | +While WAMR owns the buffer, WAMR might make in-place modifications to |
| 27 | +its contents. |
| 28 | + |
| 29 | +Loaded module and its instances |
| 30 | +------------------------------- |
| 31 | + |
| 32 | +Many of data structures for module and instances are allocated from |
| 33 | +the global heap. (aka. `wasm_runtime_malloc`) |
| 34 | + |
| 35 | +AOT code section |
| 36 | +---------------- |
| 37 | + |
| 38 | +Memory to load AOT machine code section. |
| 39 | + |
| 40 | +Because this memory needs to be executable, depending on platforms, |
| 41 | +it's allocated from a separate allocator. |
| 42 | +For example, `mmap` and `mprotect` are used on POSIX-like platforms. |
| 43 | + |
| 44 | +Linear memory |
| 45 | +------------- |
| 46 | + |
| 47 | +A WASM linear memory is either shared or non-shared. |
| 48 | + |
| 49 | +A WASM linear memory has `min` and `max` sizes. |
| 50 | +(They correspond to `wasm-ld`'s `--init-memory` and `--max-memory` options.) |
| 51 | +They are in the number of WASM pages, each of which is of 65536 bytes. |
| 52 | +The `max` is optional for non-shared memory. When omitted, it effectivily |
| 53 | +means unlimited. |
| 54 | + |
| 55 | +If `OS_ENABLE_HW_BOUND_CHECK` is enabled, the memory is allocated via |
| 56 | +`os_mmap` and `os_mem_commit`/`os_mprotect`. |
| 57 | +Otherwise, it's allocated from the global heap. |
| 58 | + |
| 59 | +If the memory is shared and `OS_ENABLE_HW_BOUND_CHECK` is not enabled, |
| 60 | +the `max` size of memory is allocated on instantiation. |
| 61 | + |
| 62 | +Otherwise, the `min` size of memory is allocated on instantiation. |
| 63 | +It can later grow up to the `max` size via the `memory.grow` instruction. |
| 64 | + |
| 65 | +Libc heap |
| 66 | +--------- |
| 67 | + |
| 68 | +The libc heap is the last (highest address) part of linear memory, |
| 69 | +which might be dynamically grown with `memory.grow` instruction, when |
| 70 | +necessary to serve memory allocations within the module. |
| 71 | + |
| 72 | +App heap |
| 73 | +-------- |
| 74 | + |
| 75 | +Not used for the above mentioned configuration. |
| 76 | + |
| 77 | +You can safely disable the app heap creation by specifying `0` for |
| 78 | +the `heap_size` argument of `wasm_runtime_instantiate`. |
| 79 | +(It's automatically disabled if malloc/free are exported from the module.) |
| 80 | + |
| 81 | +WASM stack |
| 82 | +---------- |
| 83 | + |
| 84 | +Operand stack is not used for AOT. |
| 85 | + |
| 86 | +However, a small amount of WASM stack is used for call frames when |
| 87 | +certain features are enabled. |
| 88 | +(`WASM_ENABLE_DUMP_CALL_STACK` or `WASM_ENABLE_PERF_PROFILING`) |
| 89 | + |
| 90 | +It's allocated from the global heap. |
| 91 | + |
| 92 | +You can specify its size with the `stack_size` argument of |
| 93 | +`wasm_runtime_instantiate` and `wasm_runtime_create_exec_env`. |
| 94 | +(1 is the minimum because 0 means the default.) |
| 95 | + |
| 96 | +AUX stack (aka. C shadow stack) |
| 97 | +------------------------------- |
| 98 | + |
| 99 | +For the main thread, it's a part of the linear memory, |
| 100 | +between `__data_end` and `__heap_base` symbols. |
| 101 | +You can control the size of this stack with `wasm-ld`'s |
| 102 | +`-z stack-size` option. |
| 103 | + |
| 104 | +For threads created by `pthread_create`, libc allocates the stack for |
| 105 | +them dynamically from the libc heap. |
| 106 | +The size of this stack is inherited from the main thread's one |
| 107 | +unless overwritten with `pthread_attr_setstacksize` etc. |
| 108 | + |
| 109 | +WAMR tries to detect overflow/underflow when updating the stack pointer |
| 110 | +global. For threads created by `pthread_create`, the detection mechanism |
| 111 | +is disabled as of writing this. |
| 112 | + |
| 113 | +Native stack |
| 114 | +------------ |
| 115 | + |
| 116 | +The stack of the host environment thread which runs WAMR. |
| 117 | + |
| 118 | +For threads created by `pthread_create`, WAMR automatically creates |
| 119 | +host threads to run those WASM threads. The stack size of these host |
| 120 | +threads are controlled by a build-time configuration. |
| 121 | +(`APP_THREAD_STACK_SIZE_DEFAULT`) |
| 122 | + |
| 123 | +In some configurations, runtime overflow can be detected using hardware traps. |
| 124 | +(`OS_ENABLE_HW_BOUND_CHECK`) |
| 125 | + |
| 126 | +In some configurations, explicit overflow detection logic can be emitted |
| 127 | +into AOT modules themselves. (cf. `os_thread_get_stack_boundary`, |
| 128 | +`check_stack_boundary`, `wamrc --stack-bounds-checks=1/0`) |
| 129 | + |
| 130 | +Memory profiling |
| 131 | +================ |
| 132 | + |
| 133 | +You can collect and dump detailed information about memory usage |
| 134 | +by actually running a module with the `WASM_ENABLE_MEMORY_PROFILING` |
| 135 | +build-time option. |
0 commit comments