Bug 1563316 - Add SymbolicationService.querySymbolicationApi. r=canaltinova

With the existing getSymbolTable API, we always expose all symbols.
This new API will save memory and time when symbolicating profiles for local
Firefox builds, and it will scale to returning more information per address.

The profiler-get-symbols wasm module currently supports two "path" entry points:
 - /symbolicate/v5: This one has the same API as the /symbolicate/v5 entry
   point of the official Mozilla symbolication API, see the docs:
   https://tecken.readthedocs.io/en/latest/symbolication.html#symbolication-symbolicate-v5
 - /symbolicate/v6a2: This has the same request API as v5 but returns
   richer data: For each address it also returns file and line information,
   as well as the inline stack at that address.

In the future, we may want to add more supported "paths". Since this glue
code is really generic, doing so should be possible without touching most
of the glue code, only by updating the wasm bundle to a newer version of
profiler-get-symbols.

Differential Revision: https://phabricator.services.mozilla.com/D121932
This commit is contained in:
Markus Stange 2021-08-17 02:19:58 +00:00
Родитель b2532888f8
Коммит 0c9acde69c
3 изменённых файлов: 83 добавлений и 14 удалений

Просмотреть файл

@ -167,6 +167,7 @@ export type GetSymbolTableCallback = (
export interface SymbolicationService {
getSymbolTable: GetSymbolTableCallback;
querySymbolicationApi: (path: string, requestJson: string) => Promise<string>;
}
export type ReceiveProfile = (
@ -511,13 +512,10 @@ export type LibInfoMapValue = {
debugPath: string;
breakpadId: string;
arch: string;
}
};
export type SymbolicationWorkerInitialMessage = {
// The debugName of the binary whose symbols should be obtained.
debugName: string;
// The breakpadId for the binary whose symbols should be obtained.
breakpadId: string;
request: SymbolicationWorkerRequest;
// A map that allows looking up library info based on debugName + breakpadId.
// This is rather redundant at the moment, but it will make more sense once
// we can request symbols for multiple different libraries with one worker
@ -530,6 +528,22 @@ export type SymbolicationWorkerInitialMessage = {
module: WebAssembly.Module;
};
export type SymbolicationWorkerRequest =
| {
type: "GET_SYMBOL_TABLE";
// The debugName of the binary whose symbols should be obtained.
debugName: string;
// The breakpadId for the binary whose symbols should be obtained.
breakpadId: string;
}
| {
type: "QUERY_SYMBOLICATION_API";
// The API entry path, such as "/symbolicate/v5".
path: string;
// The payload JSON, as a string.
requestJson: string;
};
export type SymbolicationWorkerError = {
name: string;
message: string;

Просмотреть файл

@ -30,7 +30,7 @@ importScripts(
// itself.
/* eslint camelcase: 0*/
const { getCompactSymbolTable } = wasm_bindgen;
const { getCompactSymbolTable, queryAPI } = wasm_bindgen;
// Read parts of an open OS.File instance into the Uint8Array dataBuf.
// This reads destBuf.byteLength bytes at offset offset.
@ -181,7 +181,7 @@ class FileAndPathHelper {
/** @param {MessageEvent<SymbolicationWorkerInitialMessage>} e */
onmessage = async e => {
try {
const { debugName, breakpadId, libInfoMap, objdirs, module } = e.data;
const { request, libInfoMap, objdirs, module } = e.data;
if (!(module instanceof WebAssembly.Module)) {
throw new Error("invalid WebAssembly module");
@ -191,11 +191,30 @@ onmessage = async e => {
await wasm_bindgen(module);
const helper = new FileAndPathHelper(libInfoMap, objdirs);
const result = await getCompactSymbolTable(debugName, breakpadId, helper);
postMessage(
{ result },
result.map(r => r.buffer)
);
switch (request.type) {
case "GET_SYMBOL_TABLE": {
const { debugName, breakpadId } = request;
const result = await getCompactSymbolTable(
debugName,
breakpadId,
helper
);
postMessage(
{ result },
result.map(r => r.buffer)
);
break;
}
case "QUERY_SYMBOLICATION_API": {
const { path, requestJson } = request;
const result = await queryAPI(path, requestJson, helper);
postMessage({ result });
break;
}
default:
throw new Error(`Unexpected request type ${request.type}`);
}
} catch (error) {
postMessage({ error: createPlainErrorObject(error) });
}

Просмотреть файл

@ -234,8 +234,35 @@ class LocalSymbolicationService {
const module = await getWASMProfilerGetSymbolsModule();
/** @type {SymbolicationWorkerInitialMessage} */
const initialMessage = {
debugName,
breakpadId,
request: {
type: "GET_SYMBOL_TABLE",
debugName,
breakpadId,
},
libInfoMap: this._libInfoMap,
objdirs: this._objdirs,
module,
};
return getResultFromWorker(
"resource://devtools/client/performance-new/symbolication-worker.js",
initialMessage
);
}
/**
* @param {string} path
* @param {string} requestJson
* @returns {Promise<string>}
*/
async querySymbolicationApi(path, requestJson) {
const module = await getWASMProfilerGetSymbolsModule();
/** @type {SymbolicationWorkerInitialMessage} */
const initialMessage = {
request: {
type: "QUERY_SYMBOLICATION_API",
path,
requestJson,
},
libInfoMap: this._libInfoMap,
objdirs: this._objdirs,
module,
@ -301,6 +328,15 @@ class LocalSymbolicationServiceWithRemoteSymbolTableFallback {
return getSymbolTableFromDebuggee(this._perfFront, lib.path, breakpadId);
}
}
/**
* @param {string} path
* @param {string} requestJson
* @returns {Promise<string>}
*/
async querySymbolicationApi(path, requestJson) {
return this._symbolicationService.querySymbolicationApi(path, requestJson);
}
}
/**