From ba2463e3890c6b3182814698bd296e07ca13f038 Mon Sep 17 00:00:00 2001 From: Matthias Frei Date: Tue, 27 Jan 2026 11:23:03 +0100 Subject: [PATCH] memoryprofiler: show allocations from threads --- src/lib/libmemoryprofiler.js | 2 +- src/lib/libtrace.js | 12 +++++++++--- src/memoryprofiler.js | 22 ++++++++++++++-------- src/settings.js | 2 +- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/lib/libmemoryprofiler.js b/src/lib/libmemoryprofiler.js index ca3e3770af2e8..16f8aabc7e5c4 100644 --- a/src/lib/libmemoryprofiler.js +++ b/src/lib/libmemoryprofiler.js @@ -1,7 +1,7 @@ var memoryProfiler = { emscripten_memprof_sbrk_grow: (old_brk, new_brk) => { #if MEMORYPROFILER - emscriptenMemoryProfiler.onSbrkGrow(old_brk, new_brk); + Module['onSbrkGrow']?.(old_brk, new_brk) || postMessage({cmd: 'callHandler', handler: 'onSbrkGrow', args: [old_brk, new_brk, new Error().stack.toString()]}); #endif }, }; diff --git a/src/lib/libtrace.js b/src/lib/libtrace.js index c50c0de904f4c..5555dde8924a8 100644 --- a/src/lib/libtrace.js +++ b/src/lib/libtrace.js @@ -210,7 +210,9 @@ var LibraryTracing = { }, emscripten_trace_record_allocation: (address, size) => { - Module['onMalloc']?.(address, size); +#if MEMORYPROFILER + Module['onMalloc']?.(address, size) || postMessage({cmd: 'callHandler', handler: 'onMalloc', args: [address, size, new Error().stack.toString()]}); +#endif if (EmscriptenTrace.postEnabled) { var now = EmscriptenTrace.now(); EmscriptenTrace.post([EmscriptenTrace.EVENT_ALLOCATE, @@ -219,7 +221,9 @@ var LibraryTracing = { }, emscripten_trace_record_reallocation: (old_address, new_address, size) => { - Module['onRealloc']?.(old_address, new_address, size); +#if MEMORYPROFILER + Module['onRealloc']?.(old_address, new_address, size) || postMessage({cmd: 'callHandler', handler: 'onRealloc', args: [old_address, new_address, size, new Error().stack.toString()]}); +#endif if (EmscriptenTrace.postEnabled) { var now = EmscriptenTrace.now(); EmscriptenTrace.post([EmscriptenTrace.EVENT_REALLOCATE, @@ -228,7 +232,9 @@ var LibraryTracing = { }, emscripten_trace_record_free: (address) => { - Module['onFree']?.(address); +#if MEMORYPROFILER + Module['onFree']?.(address) || postMessage({cmd: 'callHandler', handler: 'onFree', args: [address]}); +#endif if (EmscriptenTrace.postEnabled) { var now = EmscriptenTrace.now(); EmscriptenTrace.post([EmscriptenTrace.EVENT_FREE, diff --git a/src/memoryprofiler.js b/src/memoryprofiler.js index e55940b96ccb0..93aeb396104d9 100644 --- a/src/memoryprofiler.js +++ b/src/memoryprofiler.js @@ -118,7 +118,7 @@ var emscriptenMemoryProfiler = { return '#' + toHex(r) + toHex(g) + toHex(b); }, - onSbrkGrow(oldLimit, newLimit) { + onSbrkGrow(oldLimit, newLimit, loc) { var self = emscriptenMemoryProfiler; // On first sbrk(), account for the initial size. if (self.sbrkSources.length == 0) { @@ -130,8 +130,11 @@ var emscriptenMemoryProfiler = { }); } if (newLimit <= oldLimit) return; + if (loc == undefined) { + loc = new Error().stack.toString(); + } self.sbrkSources.push({ - stack: self.filterCallstackForHeapResize(new Error().stack.toString()), + stack: self.filterCallstackForHeapResize(loc), begin: oldLimit, end: newLimit, color: self.hsvToRgb(self.sbrkSources.length * 0.618033988749895 % 1, 0.5, 0.95) @@ -166,7 +169,7 @@ var emscriptenMemoryProfiler = { } }, - onMalloc(ptr, size) { + onMalloc(ptr, size, loc) { if (!ptr) return; if (emscriptenMemoryProfiler.sizeOfAllocatedPtr[ptr]) { @@ -189,7 +192,9 @@ var emscriptenMemoryProfiler = { // Also track if this was a _malloc performed at preRun time. if (!self.pagePreRunIsFinished) self.sizeOfPreRunAllocatedPtr[ptr] = size; - var loc = new Error().stack.toString(); + if(loc == undefined) { + loc = new Error().stack.toString(); + } self.allocationsAtLoc[loc] ||= [0, 0, self.filterCallstackForMalloc(loc)]; self.allocationsAtLoc[loc][0] += 1; self.allocationsAtLoc[loc][1] += size; @@ -229,9 +234,9 @@ var emscriptenMemoryProfiler = { ++self.totalTimesFreeCalled; }, - onRealloc(oldAddress, newAddress, size) { + onRealloc(oldAddress, newAddress, size, loc) { emscriptenMemoryProfiler.onFree(oldAddress); - emscriptenMemoryProfiler.onMalloc(newAddress, size); + emscriptenMemoryProfiler.onMalloc(newAddress, size, loc); }, onPreloadComplete() { @@ -241,9 +246,10 @@ var emscriptenMemoryProfiler = { // Installs startup hook and periodic UI update timer. initialize() { // Inject the memoryprofiler hooks. - Module['onMalloc'] = (ptr, size) => emscriptenMemoryProfiler.onMalloc(ptr, size); - Module['onRealloc'] = (oldAddress, newAddress, size) => emscriptenMemoryProfiler.onRealloc(oldAddress, newAddress, size);; + Module['onMalloc'] = (ptr, size, loc) => emscriptenMemoryProfiler.onMalloc(ptr, size, loc); + Module['onRealloc'] = (oldAddress, newAddress, size, loc) => emscriptenMemoryProfiler.onRealloc(oldAddress, newAddress, size, loc);; Module['onFree'] = (ptr) => emscriptenMemoryProfiler.onFree(ptr); + Module['onSbrkGrow'] = (old_brk, new_brk, loc) => emscriptenMemoryProfiler.onSbrkGrow(old_brk, new_brk, loc); emscriptenMemoryProfiler.recordStackWatermark(); // Add a tracking mechanism to detect when VFS loading is complete. diff --git a/src/settings.js b/src/settings.js index ae8831335e619..8d9750c6cc965 100644 --- a/src/settings.js +++ b/src/settings.js @@ -999,7 +999,7 @@ var INCOMING_MODULE_JS_API = [ 'loadSplitModule', 'locateFile', 'logReadFiles', 'mainScriptUrlOrBlob', 'mem', 'monitorRunDependencies', 'noExitRuntime', 'noInitialRun', 'onAbort', 'onExit', 'onFree', 'onFullScreen', 'onMalloc', - 'onRealloc', 'onRuntimeInitialized', 'postMainLoop', 'postRun', 'preInit', + 'onRealloc', 'onRuntimeInitialized', 'onSbrkGrow', 'postMainLoop', 'postRun', 'preInit', 'preMainLoop', 'preRun', 'preinitializedWebGLContext', 'preloadPlugins', 'print', 'printErr', 'setStatus', 'statusMessage', 'stderr',