Skip to content

Commit 694bfc7

Browse files
committed
Share stringTable between threads.
1 parent 6abfd2e commit 694bfc7

Some content is hidden

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

60 files changed

+35195
-40754
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 = 55;
17+
export const PROCESSED_PROFILE_VERSION = 56;
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

+7-5
Original file line numberDiff line numberDiff line change
@@ -67,15 +67,20 @@ export function computeActiveTabTracks(
6767
const screenshots = [];
6868
const topmostInnerWindowIDs = getTopmostInnerWindowIDs(relevantPages);
6969
const innerWindowIDToPageMap = _getInnerWindowIDToPageMap(relevantPages);
70+
const { stringArray } = profile.shared;
71+
const stringTable = StringTable.withBackingArray(stringArray);
72+
73+
const screenshotNameIndex = stringTable.indexForString(
74+
'CompositorScreenshot'
75+
);
7076

7177
for (
7278
let threadIndex = 0;
7379
threadIndex < profile.threads.length;
7480
threadIndex++
7581
) {
7682
const thread = profile.threads[threadIndex];
77-
const { markers, stringArray } = thread;
78-
const stringTable = StringTable.withBackingArray(stringArray);
83+
const { markers } = thread;
7984

8085
if (thread.isMainThread) {
8186
// This is a main thread, there is a possibility that it can be a global
@@ -120,9 +125,6 @@ export function computeActiveTabTracks(
120125

121126
// Check for screenshots.
122127
const windowIDs: Set<string> = new Set();
123-
const screenshotNameIndex = stringTable.indexForString(
124-
'CompositorScreenshot'
125-
);
126128
if (screenshotNameIndex !== -1) {
127129
for (let markerIndex = 0; markerIndex < markers.length; markerIndex++) {
128130
if (markers.name[markerIndex] === screenshotNameIndex) {

src/profile-logic/data-structures.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,6 @@ export function getEmptyThread(overrides?: $Shape<RawThread>): RawThread {
397397
markers: getEmptyRawMarkerTable(),
398398
stackTable: getEmptyRawStackTable(),
399399
frameTable: getEmptyFrameTable(),
400-
stringArray: [],
401400
funcTable: getEmptyFuncTable(),
402401
resourceTable: getEmptyResourceTable(),
403402
nativeSymbols: getEmptyNativeSymbolTable(),
@@ -436,6 +435,9 @@ export function getEmptyProfile(): Profile {
436435
},
437436
libs: [],
438437
pages: [],
438+
shared: {
439+
stringArray: [],
440+
},
439441
threads: [],
440442
};
441443
}

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) {
@@ -841,7 +840,7 @@ async function extractScreenshots(
841840
screenshots[0]
842841
);
843842

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

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

934+
const stringTable = StringTable.withBackingArray(profile.shared.stringArray);
935+
935936
profile.meta.markerSchema = [
936937
{
937938
name: 'EventDispatch',
@@ -998,8 +999,7 @@ function extractMarkers(
998999
event
9991000
);
10001001
const { thread } = threadInfo;
1001-
const { markers, stringArray } = thread;
1002-
const stringTable = StringTable.withBackingArray(stringArray);
1002+
const { markers } = thread;
10031003
let argData: MixedObject | null = null;
10041004
if (event.args && typeof event.args === 'object') {
10051005
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

@@ -371,7 +371,6 @@ export function attemptToConvertDhat(json: mixed): Profile | null {
371371
thread.pid = dhat.pid;
372372
thread.tid = i;
373373
thread.name = name;
374-
thread.stringArray = stringTable.getBackingArray();
375374

376375
thread.funcTable.name = funcTable.name.slice();
377376
thread.funcTable.isJS = funcTable.isJS.slice();

src/profile-logic/import/simpleperf.js

+20-9
Original file line numberDiff line numberDiff line change
@@ -223,24 +223,30 @@ class FirefoxThread {
223223
tid: number;
224224
pid: number;
225225

226-
stringArray = [];
227-
strings = StringTable.withBackingArray(this.stringArray);
226+
strings: StringTable;
228227

229228
sampleTable: RawSamplesTable = getEmptySamplesTable();
230229

231-
stackTable: FirefoxSampleTable = new FirefoxSampleTable(this.strings);
232-
frameTable: FirefoxFrameTable = new FirefoxFrameTable(this.strings);
233-
funcTable: FirefoxFuncTable = new FirefoxFuncTable(this.strings);
234-
resourceTable: FirefoxResourceTable = new FirefoxResourceTable(this.strings);
230+
stackTable: FirefoxSampleTable;
231+
frameTable: FirefoxFrameTable;
232+
funcTable: FirefoxFuncTable;
233+
resourceTable: FirefoxResourceTable;
235234

236235
cpuClockEventId: number = -1;
237236

238-
constructor(thread: report.IThread) {
237+
constructor(thread: report.IThread, stringTable: StringTable) {
239238
this.tid = thread.threadId;
240239
this.pid = thread.processId;
241240

242241
this.isMainThread = thread.threadId === thread.processId;
243242
this.name = thread.threadName ?? '';
243+
244+
this.strings = stringTable;
245+
246+
this.stackTable = new FirefoxSampleTable(this.strings);
247+
this.frameTable = new FirefoxFrameTable(this.strings);
248+
this.funcTable = new FirefoxFuncTable(this.strings);
249+
this.resourceTable = new FirefoxResourceTable(this.strings);
244250
}
245251

246252
toJson(): RawThread {
@@ -259,7 +265,6 @@ class FirefoxThread {
259265
markers: getEmptyRawMarkerTable(),
260266
stackTable: this.stackTable.toJson(),
261267
frameTable: this.frameTable.toJson(),
262-
stringArray: this.stringArray,
263268
funcTable: this.funcTable.toJson(),
264269
resourceTable: this.resourceTable.toJson(),
265270
nativeSymbols: getEmptyNativeSymbolTable(),
@@ -358,10 +363,16 @@ class FirefoxProfile {
358363
sampleCount: number = 0;
359364
lostCount: number = 0;
360365

366+
stringArray = [];
367+
stringTable = StringTable.withBackingArray(this.stringArray);
368+
361369
toJson(): Profile {
362370
return {
363371
meta: this.getProfileMeta(),
364372
libs: [],
373+
shared: {
374+
stringArray: this.stringArray,
375+
},
365376
threads: this.threads.map((thread) => thread.toJson()),
366377
};
367378
}
@@ -439,7 +450,7 @@ class FirefoxProfile {
439450
}
440451

441452
addThread(thread: report.IThread) {
442-
const firefoxThread = new FirefoxThread(thread);
453+
const firefoxThread = new FirefoxThread(thread, this.stringTable);
443454
this.threads.push(firefoxThread);
444455
this.threadMap.set(thread.threadId, firefoxThread);
445456
}

src/profile-logic/js-tracer.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -738,10 +738,10 @@ export function getJsTracerFixed(jsTracer: JsTracerTable): JsTracerFixed {
738738
export function convertJsTracerToThread(
739739
fromThread: RawThread,
740740
jsTracer: JsTracerTable,
741-
categories: CategoryList
741+
categories: CategoryList,
742+
stringTable: StringTable
742743
): RawThread {
743744
const jsTracerFixed = getJsTracerFixed(jsTracer);
744-
const stringTable = StringTable.withBackingArray(fromThread.stringArray);
745745
const { thread, stackMap } = convertJsTracerToThreadWithoutSamples(
746746
fromThread,
747747
stringTable,

src/profile-logic/marker-data.js

+5-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
}

0 commit comments

Comments
 (0)