Skip to content

Commit 503608b

Browse files
authored
[wasm] Defer parsing of wasm stack symbolication maps (#99974)
Right now if a wasm app's assets list contains symbol maps for stack symbolication, we parse them at startup. This allocates a lot of garbage and is generally slow, and during normal execution the symbol map(s) may never actually be used, so this PR defers the actual parsing until first use.
1 parent 5e8edc8 commit 503608b

File tree

1 file changed

+31
-10
lines changed

1 file changed

+31
-10
lines changed

src/mono/browser/runtime/logging.ts

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
/* eslint-disable no-console */
5-
import { INTERNAL, runtimeHelpers } from "./globals";
5+
import { INTERNAL, runtimeHelpers, mono_assert } from "./globals";
66
import { utf8ToString } from "./strings";
77
import { CharPtr, VoidPtr } from "./types/emscripten";
88

@@ -35,6 +35,7 @@ export function mono_log_error(msg: string, ...data: any) {
3535
}
3636

3737
export const wasm_func_map = new Map<number, string>();
38+
let wasm_pending_symbol_table : string | undefined;
3839
const regexes: any[] = [];
3940

4041
// V8
@@ -54,6 +55,8 @@ regexes.push(/(?<replaceSection><[^ >]+>[.:]wasm-function\[(?<funcNum>[0-9]+)\])
5455

5556
export function mono_wasm_symbolicate_string(message: string): string {
5657
try {
58+
performDeferredSymbolMapParsing();
59+
5760
if (wasm_func_map.size == 0)
5861
return message;
5962

@@ -143,22 +146,40 @@ export function mono_wasm_trace_logger(log_domain_ptr: CharPtr, log_level_ptr: C
143146

144147

145148
export function parseSymbolMapFile(text: string) {
146-
text.split(/[\r\n]/).forEach((line: string) => {
147-
const parts: string[] = line.split(/:/);
148-
if (parts.length < 2)
149-
return;
149+
// Symbol map parsing is very expensive, so doing it during startup is wasteful
150+
// instead, we defer it until the first time the symbol map is needed - which
151+
// may be never
152+
mono_assert(!wasm_pending_symbol_table, "Another symbol map was already loaded");
153+
wasm_pending_symbol_table = text;
154+
mono_log_debug(`Deferred loading of ${text.length}ch symbol map`);
155+
}
150156

151-
parts[1] = parts.splice(1).join(":");
152-
wasm_func_map.set(Number(parts[0]), parts[1]);
153-
});
157+
function performDeferredSymbolMapParsing() {
158+
if (!wasm_pending_symbol_table)
159+
return;
154160

155-
mono_log_debug(`Loaded ${wasm_func_map.size} symbols`);
161+
const text = wasm_pending_symbol_table!;
162+
wasm_pending_symbol_table = undefined;
163+
try {
164+
text.split(/[\r\n]/).forEach((line: string) => {
165+
const parts: string[] = line.split(/:/);
166+
if (parts.length < 2)
167+
return;
168+
169+
parts[1] = parts.splice(1).join(":");
170+
wasm_func_map.set(Number(parts[0]), parts[1]);
171+
});
172+
mono_log_debug(`Loaded ${wasm_func_map.size} symbols`);
173+
} catch (exc) {
174+
mono_log_warn(`Failed to load symbol map: ${exc}`);
175+
}
156176
}
157177

158178
export function mono_wasm_get_func_id_to_name_mappings() {
179+
performDeferredSymbolMapParsing();
159180
return [...wasm_func_map.values()];
160181
}
161182

162183
export function mono_wasm_console_clear() {
163184
console.clear();
164-
}
185+
}

0 commit comments

Comments
 (0)