Hi,
I got caught by the season flu, and I thought I'd do something fun for a change, so here goes.
Memoryprofiler.js is a tool that integrates to Emscripten-built .html applications, and it tracks the various Emscripten memory area uses, and draws a graph of memory fragmentation in the Emscripten HEAP.
It hooks into the malloc(), free() and Runtime.stackAlloc() functions of the Emscripten runtime, and captures the memory usage as it happens.
A quick glossary of the related terms if you are not yet familiar with them:
HEAP: This is the single large memory blob that the Emscripten application allocates at startup, and is all the memory that the Emscripten application ever sees. The STATIC, STACK and DYNAMIC memory areas are allocated inside this chunk.
STATIC: This memory area contains constants and globals allocated at application startup time. Its size never changes at runtime. The STATIC memory area is in the lowest part of the Emscripten HEAP.
STACK: This is the application function call stack. Note that unlike the X86 stack that grows downwards, the Emscripten stack grows up. The profiler tracks how much space is used in the stack during the time stack and heap allocations occur, but note that it is only approximate - not all stack usage can be captured.
DYNAMIC: The memory area for dynamic heap allocations. This is the pool where memory is taken from when operator new or malloc is called.
As is readily visible in the map that gets graphed, the memory layout inside HEAP looks like
(address 0) [ STATIC | STACK | DYNAMIC | empty ] (top of HEAP)
The empty space between the top of the DYNAMIC area and the end of HEAP is unused, but fully reserved for the DYNAMIC area to grow into (via a page allocation operation from a function _sbrk). The total amount of memory the application can allocate is the sum of the empty area
plus the amount of free memory in DYNAMIC (minus fragmentation of the HEAP in DYNAMIC).
To embed memoryprofiler.js to your own builds:
2. Add a line "<script src='memoryprofiler.js'></script>" to your application .html file to link memoryprofiler.js to it.
3. In the Module properties of your application .html file, add a preRun call to memoryprofiler initialization function 'memoryprofiler_add_hooks()'. That is, replace the default line in Module that reads
with
preRun: [memoryprofiler_add_hooks]
and reopen the page. That's it!
To make steps 2. and 3. persist between builds, you can add the <script> tag and the preRun dependency to your custom shell file (copy the provided shell.html in emscripten source directory to your project and make the changes there), and use --shell-file my_shell_with_profiler.html at Emscripten link time to use that shell instead.
Configuration:
There are a few items you can configure in the profiler. Configuration occurs by directly editing the file memoryprofiler.js. See the variables
MEMORYPROFILER_DETAILED_HEAP_USAGE MEMORYPROFILER_TRACK_CALLSTACK_MIN_SIZE MEMORYPROFILER_HOOK_STACKALLOC
MEMORYPROFILER_UI_UPDATE_INTERVAL
and their documentation in top of the file itself.
Hope it works!
Jukka