Skip to content

Commit eaa6409

Browse files
committed
Share stringTable between threads.
1 parent 6b100cc commit eaa6409

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+35616
-40473
lines changed

src/actions/receive-profile.js

+17-14
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ export function finalizeFullProfileView(
397397
const thread = profile.threads[threadIndex];
398398
const { samples, jsAllocations, nativeAllocations } = thread;
399399
hasSamples = [samples, jsAllocations, nativeAllocations].some((table) =>
400-
hasUsefulSamples(table?.stack, thread)
400+
hasUsefulSamples(table?.stack, thread, profile.shared)
401401
);
402402
if (hasSamples) {
403403
break;
@@ -793,20 +793,23 @@ export function bulkProcessSymbolicationSteps(
793793
symbolicationStepsPerThread: Map<ThreadIndex, SymbolicationStepInfo[]>
794794
): ThunkAction<void> {
795795
return (dispatch, getState) => {
796-
const { threads } = getProfile(getState());
796+
const profile = getProfile(getState());
797797
const oldFuncToNewFuncsMaps: Map<ThreadIndex, FuncToFuncsMap> = new Map();
798-
const symbolicatedThreads = threads.map((oldThread, threadIndex) => {
799-
const symbolicationSteps = symbolicationStepsPerThread.get(threadIndex);
800-
if (symbolicationSteps === undefined) {
801-
return oldThread;
798+
const symbolicatedThreads = profile.threads.map(
799+
(oldThread, threadIndex) => {
800+
const symbolicationSteps = symbolicationStepsPerThread.get(threadIndex);
801+
if (symbolicationSteps === undefined) {
802+
return oldThread;
803+
}
804+
const { thread, oldFuncToNewFuncsMap } = applySymbolicationSteps(
805+
oldThread,
806+
profile.shared,
807+
symbolicationSteps
808+
);
809+
oldFuncToNewFuncsMaps.set(threadIndex, oldFuncToNewFuncsMap);
810+
return thread;
802811
}
803-
const { thread, oldFuncToNewFuncsMap } = applySymbolicationSteps(
804-
oldThread,
805-
symbolicationSteps
806-
);
807-
oldFuncToNewFuncsMaps.set(threadIndex, oldFuncToNewFuncsMap);
808-
return thread;
809-
});
812+
);
810813
dispatch({
811814
type: 'BULK_SYMBOLICATION',
812815
oldFuncToNewFuncsMaps,
@@ -1895,7 +1898,7 @@ export function changeTabFilter(tabID: TabID | null): ThunkAction<void> {
18951898
const thread = profile.threads[threadIndex];
18961899
const { samples, jsAllocations, nativeAllocations } = thread;
18971900
hasSamples = [samples, jsAllocations, nativeAllocations].some((table) =>
1898-
hasUsefulSamples(table?.stack, thread)
1901+
hasUsefulSamples(table?.stack, thread, profile.shared)
18991902
);
19001903
if (hasSamples) {
19011904
break;

src/app-logic/constants.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export const GECKO_PROFILE_VERSION = 31;
1414
// The current version of the "processed" profile format.
1515
// Please don't forget to update the processed profile format changelog in
1616
// `docs-developer/CHANGELOG-formats.md`.
17-
export const PROCESSED_PROFILE_VERSION = 53;
17+
export const PROCESSED_PROFILE_VERSION = 54;
1818

1919
// The following are the margin sizes for the left and right of the timeline. Independent
2020
// components need to share these values.

src/components/js-tracer/Chart.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { JsTracerCanvas } from './Canvas';
1515
import {
1616
getCommittedRange,
1717
getPreviewSelection,
18+
getStringTable,
1819
} from 'firefox-profiler/selectors/profile';
1920
import { selectedThreadSelectors } from 'firefox-profiler/selectors/per-thread';
2021
import { getSelectedThreadsKey } from 'firefox-profiler/selectors/url-state';
@@ -136,7 +137,7 @@ const JsTracerExpensiveChart = explicitConnect<
136137
>({
137138
mapStateToProps: (state, ownProps) => ({
138139
timeRange: getCommittedRange(state),
139-
stringTable: selectedThreadSelectors.getStringTable(state),
140+
stringTable: getStringTable(state),
140141
threadsKey: getSelectedThreadsKey(state),
141142
previewSelection: getPreviewSelection(state),
142143
jsTracerTimingRows: ensureExists(

src/profile-logic/active-tab.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,15 @@ export function computeActiveTabTracks(
6666
const screenshots = [];
6767
const topmostInnerWindowIDs = getTopmostInnerWindowIDs(relevantPages);
6868
const innerWindowIDToPageMap = _getInnerWindowIDToPageMap(relevantPages);
69+
const { stringArray } = profile.shared;
6970

7071
for (
7172
let threadIndex = 0;
7273
threadIndex < profile.threads.length;
7374
threadIndex++
7475
) {
7576
const thread = profile.threads[threadIndex];
76-
const { markers, stringArray } = thread;
77+
const { markers } = thread;
7778

7879
if (thread.isMainThread) {
7980
// This is a main thread, there is a possibility that it can be a global

src/profile-logic/data-structures.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,6 @@ export function getEmptyThread(overrides?: $Shape<RawThread>): RawThread {
399399
markers: getEmptyRawMarkerTable(),
400400
stackTable: getEmptyRawStackTable(),
401401
frameTable: getEmptyFrameTable(),
402-
stringArray: [],
403402
funcTable: getEmptyFuncTable(),
404403
resourceTable: getEmptyResourceTable(),
405404
nativeSymbols: getEmptyNativeSymbolTable(),
@@ -438,6 +437,9 @@ export function getEmptyProfile(): Profile {
438437
},
439438
libs: [],
440439
pages: [],
440+
shared: {
441+
stringArray: [],
442+
},
441443
threads: [],
442444
};
443445
}

src/profile-logic/import/chrome.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,8 @@ async function processTracingEvents(
514514
// new samples on our target interval of 500us.
515515
profile.meta.interval = 0.5;
516516

517+
const stringTable = StringTable.withBackingArray(profile.shared.stringArray);
518+
517519
let profileEvents: (ProfileEvent | CpuProfileEvent)[] =
518520
(eventsByName.get('Profile'): any) || [];
519521

@@ -579,13 +581,10 @@ async function processTracingEvents(
579581
funcTable,
580582
frameTable,
581583
stackTable,
582-
stringArray,
583584
samples: samplesTable,
584585
resourceTable,
585586
} = thread;
586587

587-
const stringTable = StringTable.withBackingArray(stringArray);
588-
589588
if (nodes) {
590589
const parentMap = new Map();
591590
for (const node of nodes) {
@@ -842,7 +841,7 @@ async function extractScreenshots(
842841
screenshots[0]
843842
);
844843

845-
const stringTable = StringTable.withBackingArray(thread.stringArray);
844+
const stringTable = StringTable.withBackingArray(profile.shared.stringArray);
846845

847846
const graphicsIndex = ensureExists(profile.meta.categories).findIndex(
848847
(category) => category.name === 'Graphics'
@@ -933,6 +932,8 @@ function extractMarkers(
933932
throw new Error('No "Other" category in empty profile category list');
934933
}
935934

935+
const stringTable = StringTable.withBackingArray(profile.shared.stringArray);
936+
936937
profile.meta.markerSchema = [
937938
{
938939
name: 'EventDispatch',
@@ -999,8 +1000,7 @@ function extractMarkers(
9991000
event
10001001
);
10011002
const { thread } = threadInfo;
1002-
const { markers, stringArray } = thread;
1003-
const stringTable = StringTable.withBackingArray(stringArray);
1003+
const { markers } = thread;
10041004
let argData: MixedObject | null = null;
10051005
if (event.args && typeof event.args === 'object') {
10061006
argData = (event.args: any).data || null;

src/profile-logic/import/dhat.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -180,10 +180,10 @@ export function attemptToConvertDhat(json: mixed): Profile | null {
180180
const profile = getEmptyProfile();
181181
profile.meta.product = dhat.cmd + ' (dhat)';
182182
profile.meta.importedFrom = `dhat`;
183+
const stringTable = StringTable.withBackingArray(profile.shared.stringArray);
183184

184185
const allocationsTable = getEmptyUnbalancedNativeAllocationsTable();
185-
const { funcTable, stringArray, stackTable, frameTable } = getEmptyThread();
186-
const stringTable = StringTable.withBackingArray(stringArray);
186+
const { funcTable, stackTable, frameTable } = getEmptyThread();
187187

188188
const funcKeyToFuncIndex = new Map<string, IndexIntoFuncTable>();
189189

@@ -373,7 +373,6 @@ export function attemptToConvertDhat(json: mixed): Profile | null {
373373
thread.pid = dhat.pid;
374374
thread.tid = i;
375375
thread.name = name;
376-
thread.stringArray = stringTable.getBackingArray();
377376

378377
thread.funcTable.name = funcTable.name.slice();
379378
thread.funcTable.isJS = funcTable.isJS.slice();

src/profile-logic/import/simpleperf.js

+20-9
Original file line numberDiff line numberDiff line change
@@ -220,24 +220,30 @@ class FirefoxThread {
220220
tid: number;
221221
pid: number;
222222

223-
stringArray = [];
224-
strings = StringTable.withBackingArray(this.stringArray);
223+
strings: StringTable;
225224

226225
sampleTable: RawSamplesTable = getEmptySamplesTable();
227226

228-
stackTable: FirefoxSampleTable = new FirefoxSampleTable(this.strings);
229-
frameTable: FirefoxFrameTable = new FirefoxFrameTable(this.strings);
230-
funcTable: FirefoxFuncTable = new FirefoxFuncTable(this.strings);
231-
resourceTable: FirefoxResourceTable = new FirefoxResourceTable(this.strings);
227+
stackTable: FirefoxSampleTable;
228+
frameTable: FirefoxFrameTable;
229+
funcTable: FirefoxFuncTable;
230+
resourceTable: FirefoxResourceTable;
232231

233232
cpuClockEventId: number = -1;
234233

235-
constructor(thread: report.IThread) {
234+
constructor(thread: report.IThread, stringTable: StringTable) {
236235
this.tid = thread.threadId;
237236
this.pid = thread.processId;
238237

239238
this.isMainThread = thread.threadId === thread.processId;
240239
this.name = thread.threadName ?? '';
240+
241+
this.strings = stringTable;
242+
243+
this.stackTable = new FirefoxSampleTable(this.strings);
244+
this.frameTable = new FirefoxFrameTable(this.strings);
245+
this.funcTable = new FirefoxFuncTable(this.strings);
246+
this.resourceTable = new FirefoxResourceTable(this.strings);
241247
}
242248

243249
toJson(): RawThread {
@@ -256,7 +262,6 @@ class FirefoxThread {
256262
markers: getEmptyRawMarkerTable(),
257263
stackTable: this.stackTable.toJson(),
258264
frameTable: this.frameTable.toJson(),
259-
stringArray: this.stringArray,
260265
funcTable: this.funcTable.toJson(),
261266
resourceTable: this.resourceTable.toJson(),
262267
nativeSymbols: getEmptyNativeSymbolTable(),
@@ -355,10 +360,16 @@ class FirefoxProfile {
355360
sampleCount: number = 0;
356361
lostCount: number = 0;
357362

363+
stringArray = [];
364+
stringTable = StringTable.withBackingArray(this.stringArray);
365+
358366
toJson(): Profile {
359367
return {
360368
meta: this.getProfileMeta(),
361369
libs: [],
370+
shared: {
371+
stringArray: this.stringArray,
372+
},
362373
threads: this.threads.map((thread) => thread.toJson()),
363374
};
364375
}
@@ -438,7 +449,7 @@ class FirefoxProfile {
438449
}
439450

440451
addThread(thread: report.IThread) {
441-
const firefoxThread = new FirefoxThread(thread);
452+
const firefoxThread = new FirefoxThread(thread, this.stringTable);
442453
this.threads.push(firefoxThread);
443454
this.threadMap.set(thread.threadId, firefoxThread);
444455
}

src/profile-logic/js-tracer.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -772,10 +772,10 @@ export function getJsTracerFixed(jsTracer: JsTracerTable): JsTracerFixed {
772772
export function convertJsTracerToThread(
773773
fromThread: RawThread,
774774
jsTracer: JsTracerTable,
775-
categories: CategoryList
775+
categories: CategoryList,
776+
stringTable: StringTable
776777
): RawThread {
777778
const jsTracerFixed = getJsTracerFixed(jsTracer);
778-
const stringTable = StringTable.withBackingArray(fromThread.stringArray);
779779
const { thread, stackMap } = convertJsTracerToThreadWithoutSamples(
780780
fromThread,
781781
stringTable,

src/profile-logic/marker-data.js

+25-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
import type {
2323
SamplesTable,
2424
RawThread,
25+
RawProfileSharedData,
2526
RawMarkerTable,
2627
IndexIntoStringTable,
2728
IndexIntoRawMarkerTable,
@@ -400,7 +401,8 @@ export class IPCMarkerCorrelations {
400401
* (or main thread in receiver process if they are not profiled)
401402
*/
402403
export function correlateIPCMarkers(
403-
threads: RawThread[]
404+
threads: RawThread[],
405+
shared: RawProfileSharedData
404406
): IPCMarkerCorrelations {
405407
// Create a unique ID constructed from the source PID, destination PID,
406408
// message seqno, and message type. Since the seqno is only unique for each
@@ -465,6 +467,8 @@ export function correlateIPCMarkers(
465467
}
466468
}
467469

470+
const stringTable = StringTable.withBackingArray(shared.stringArray);
471+
468472
// First, construct a mapping of marker IDs to an array of markers with that
469473
// ID for faster lookup. We also collect the friendly thread names while we
470474
// have access to all the threads. It's considerably more difficult to do
@@ -478,7 +482,6 @@ export function correlateIPCMarkers(
478482
// Don't bother checking for IPC markers if this thread's string table
479483
// doesn't have the string "IPC". This lets us avoid looping over all the
480484
// markers when we don't have to.
481-
const stringTable = StringTable.withBackingArray(thread.stringArray);
482485
if (!stringTable.hasString('IPC')) {
483486
continue;
484487
}
@@ -1625,3 +1628,23 @@ export const stringsToMarkerRegExps = (
16251628
fieldMap,
16261629
};
16271630
};
1631+
1632+
export function computeStringIndexMarkerFieldsByDataType(
1633+
markerSchemas: MarkerSchema[]
1634+
): Map<string, string[]> {
1635+
const stringIndexMarkerFieldsByDataType = new Map();
1636+
stringIndexMarkerFieldsByDataType.set('CompositorScreenshot', ['url']);
1637+
for (const schema of markerSchemas) {
1638+
const { name, data } = schema;
1639+
const stringIndexFields = [];
1640+
for (const field of data) {
1641+
if (field.format === 'unique-string' && field.key) {
1642+
stringIndexFields.push(field.key);
1643+
}
1644+
}
1645+
if (stringIndexFields.length !== 0) {
1646+
stringIndexMarkerFieldsByDataType.set(name, stringIndexFields);
1647+
}
1648+
}
1649+
return stringIndexMarkerFieldsByDataType;
1650+
}

0 commit comments

Comments
 (0)