Skip to content

Commit 21ba730

Browse files
authored
Document some info about estimating memory usage (bytecodealliance#1879)
Only covers limited configurations
1 parent f818f4c commit 21ba730

File tree

1 file changed

+135
-0
lines changed

1 file changed

+135
-0
lines changed

doc/memory_usage.md

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
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

Comments
 (0)