From d969f1fc602d2caf53dc18d2f488b73247394322 Mon Sep 17 00:00:00 2001 From: Katelyn Gadd Date: Tue, 19 Mar 2024 09:15:34 -0700 Subject: [PATCH 1/3] Defer parsing of wasm stack symbolication maps until point of first use instead of during startup --- src/mono/browser/runtime/dotnet.d.ts | 8 +++--- src/mono/browser/runtime/logging.ts | 38 ++++++++++++++++++++-------- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/mono/browser/runtime/dotnet.d.ts b/src/mono/browser/runtime/dotnet.d.ts index 2fdf8e16d09f3..5c1c547eb995f 100644 --- a/src/mono/browser/runtime/dotnet.d.ts +++ b/src/mono/browser/runtime/dotnet.d.ts @@ -3,7 +3,7 @@ //! //! This is generated file, see src/mono/wasm/runtime/rollup.config.js -//! This is not considered public API with backward compatibility guarantees. +//! This is not considered public API with backward compatibility guarantees. declare interface NativePointer { __brandNativePointer: "NativePointer"; @@ -336,7 +336,7 @@ interface AssetEntry { */ pendingDownload?: LoadingResource; } -type SingleAssetBehaviors = +type SingleAssetBehaviors = /** * The binary of the .NET runtime. */ @@ -362,14 +362,14 @@ type SingleAssetBehaviors = */ | "manifest" /** - * The debugging symbols + * The debugging symbols used to demangle wasm stack traces; from 'wasm:0x123456' to a C function name */ | "symbols" /** * Load segmentation rules file for Hybrid Globalization. */ | "segmentation-rules"; -type AssetBehaviors = SingleAssetBehaviors | +type AssetBehaviors = SingleAssetBehaviors | /** * Load asset as a managed resource assembly. */ diff --git a/src/mono/browser/runtime/logging.ts b/src/mono/browser/runtime/logging.ts index 4e9229796138c..a5f3a02883554 100644 --- a/src/mono/browser/runtime/logging.ts +++ b/src/mono/browser/runtime/logging.ts @@ -35,6 +35,7 @@ export function mono_log_error(msg: string, ...data: any) { } export const wasm_func_map = new Map(); +const wasm_pending_symbol_tables = new Array(); const regexes: any[] = []; // V8 @@ -54,6 +55,8 @@ regexes.push(/(?<[^ >]+>[.:]wasm-function\[(?[0-9]+)\]) export function mono_wasm_symbolicate_string(message: string): string { try { + performDeferredSymbolMapParsing(); + if (wasm_func_map.size == 0) return message; @@ -143,22 +146,37 @@ export function mono_wasm_trace_logger(log_domain_ptr: CharPtr, log_level_ptr: C export function parseSymbolMapFile(text: string) { - text.split(/[\r\n]/).forEach((line: string) => { - const parts: string[] = line.split(/:/); - if (parts.length < 2) - return; - - parts[1] = parts.splice(1).join(":"); - wasm_func_map.set(Number(parts[0]), parts[1]); - }); + // Symbol map parsing is very expensive, so doing it during startup is wasteful + // instead, we defer it until the first time the symbol map is needed - which + // may be never + wasm_pending_symbol_tables.push(text); + mono_log_debug(`Deferred loading of ${text.length}ch symbol map`); +} - mono_log_debug(`Loaded ${wasm_func_map.size} symbols`); +function performDeferredSymbolMapParsing() { + while (wasm_pending_symbol_tables.length > 0) { + const text = wasm_pending_symbol_tables.shift()!; + try { + text.split(/[\r\n]/).forEach((line: string) => { + const parts: string[] = line.split(/:/); + if (parts.length < 2) + return; + + parts[1] = parts.splice(1).join(":"); + wasm_func_map.set(Number(parts[0]), parts[1]); + }); + mono_log_debug(`Loaded ${wasm_func_map.size} symbols`); + } catch (exc) { + mono_log_warn(`Failed to load symbol map: ${exc}`); + } + } } export function mono_wasm_get_func_id_to_name_mappings() { + performDeferredSymbolMapParsing(); return [...wasm_func_map.values()]; } export function mono_wasm_console_clear() { console.clear(); -} \ No newline at end of file +} From 82fbe707358cfc8c6fc7f1c93ced44f886e80543 Mon Sep 17 00:00:00 2001 From: Katelyn Gadd Date: Wed, 20 Mar 2024 10:14:38 -0700 Subject: [PATCH 2/3] Undo file change --- src/mono/browser/runtime/dotnet.d.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mono/browser/runtime/dotnet.d.ts b/src/mono/browser/runtime/dotnet.d.ts index 5c1c547eb995f..2fdf8e16d09f3 100644 --- a/src/mono/browser/runtime/dotnet.d.ts +++ b/src/mono/browser/runtime/dotnet.d.ts @@ -3,7 +3,7 @@ //! //! This is generated file, see src/mono/wasm/runtime/rollup.config.js -//! This is not considered public API with backward compatibility guarantees. +//! This is not considered public API with backward compatibility guarantees. declare interface NativePointer { __brandNativePointer: "NativePointer"; @@ -336,7 +336,7 @@ interface AssetEntry { */ pendingDownload?: LoadingResource; } -type SingleAssetBehaviors = +type SingleAssetBehaviors = /** * The binary of the .NET runtime. */ @@ -362,14 +362,14 @@ type SingleAssetBehaviors = */ | "manifest" /** - * The debugging symbols used to demangle wasm stack traces; from 'wasm:0x123456' to a C function name + * The debugging symbols */ | "symbols" /** * Load segmentation rules file for Hybrid Globalization. */ | "segmentation-rules"; -type AssetBehaviors = SingleAssetBehaviors | +type AssetBehaviors = SingleAssetBehaviors | /** * Load asset as a managed resource assembly. */ From 83bc8af5d07a4b94916bfb21cf09334ad6271728 Mon Sep 17 00:00:00 2001 From: Katelyn Gadd Date: Wed, 20 Mar 2024 10:16:36 -0700 Subject: [PATCH 3/3] Only allow one symbol map file --- src/mono/browser/runtime/logging.ts | 39 ++++++++++++++++------------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/src/mono/browser/runtime/logging.ts b/src/mono/browser/runtime/logging.ts index a5f3a02883554..7494dae82876a 100644 --- a/src/mono/browser/runtime/logging.ts +++ b/src/mono/browser/runtime/logging.ts @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. /* eslint-disable no-console */ -import { INTERNAL, runtimeHelpers } from "./globals"; +import { INTERNAL, runtimeHelpers, mono_assert } from "./globals"; import { utf8ToString } from "./strings"; import { CharPtr, VoidPtr } from "./types/emscripten"; @@ -35,7 +35,7 @@ export function mono_log_error(msg: string, ...data: any) { } export const wasm_func_map = new Map(); -const wasm_pending_symbol_tables = new Array(); +let wasm_pending_symbol_table : string | undefined; const regexes: any[] = []; // V8 @@ -149,26 +149,29 @@ export function parseSymbolMapFile(text: string) { // Symbol map parsing is very expensive, so doing it during startup is wasteful // instead, we defer it until the first time the symbol map is needed - which // may be never - wasm_pending_symbol_tables.push(text); + mono_assert(!wasm_pending_symbol_table, "Another symbol map was already loaded"); + wasm_pending_symbol_table = text; mono_log_debug(`Deferred loading of ${text.length}ch symbol map`); } function performDeferredSymbolMapParsing() { - while (wasm_pending_symbol_tables.length > 0) { - const text = wasm_pending_symbol_tables.shift()!; - try { - text.split(/[\r\n]/).forEach((line: string) => { - const parts: string[] = line.split(/:/); - if (parts.length < 2) - return; - - parts[1] = parts.splice(1).join(":"); - wasm_func_map.set(Number(parts[0]), parts[1]); - }); - mono_log_debug(`Loaded ${wasm_func_map.size} symbols`); - } catch (exc) { - mono_log_warn(`Failed to load symbol map: ${exc}`); - } + if (!wasm_pending_symbol_table) + return; + + const text = wasm_pending_symbol_table!; + wasm_pending_symbol_table = undefined; + try { + text.split(/[\r\n]/).forEach((line: string) => { + const parts: string[] = line.split(/:/); + if (parts.length < 2) + return; + + parts[1] = parts.splice(1).join(":"); + wasm_func_map.set(Number(parts[0]), parts[1]); + }); + mono_log_debug(`Loaded ${wasm_func_map.size} symbols`); + } catch (exc) { + mono_log_warn(`Failed to load symbol map: ${exc}`); } }