Skip to content

Commit 265e502

Browse files
authored
Deploy June 10, 2025 (#5486)
Here are the changes: [Julien Wajsberg] Fix the compare view when using the same profile in both entries (#5469) [Nazım Can Altınova] Change the tests that check co2 values so they don't fail on every co2 dependency update (#5475) [Julien Wajsberg] Ignore the Symbol Store database cache when the user presses the resymbolication button (#5479) [Markus Stange] In the profile format, store a shared stringArray for all threads (#5481)
2 parents 446cfe9 + 2cf85e6 commit 265e502

File tree

67 files changed

+36033
-41178
lines changed

Some content is hidden

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

67 files changed

+36033
-41178
lines changed

docs-developer/CHANGELOG-formats.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ Note that this is not an exhaustive list. Processed profile format upgraders can
66

77
## Processed profile format
88

9+
### Version 56
10+
11+
The `stringArray` is now shared across threads. The shared array is stored at `profile.shared.stringArray`.
12+
913
### Version 55
1014

1115
Changes to the `MarkerSchema` type which is used for the elements of the array at `profile.meta.markerSchema`:

package.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
},
6464
"dependencies": {
6565
"@codemirror/lang-cpp": "^6.0.2",
66-
"@codemirror/lang-javascript": "^6.2.3",
66+
"@codemirror/lang-javascript": "^6.2.4",
6767
"@codemirror/lang-rust": "^6.0.1",
6868
"@codemirror/language": "^6.11.0",
6969
"@codemirror/state": "^6.5.2",
@@ -73,7 +73,7 @@
7373
"@fluent/langneg": "^0.7.0",
7474
"@fluent/react": "^0.15.2",
7575
"@lezer/highlight": "^1.2.1",
76-
"@tgwf/co2": "^0.16.7",
76+
"@tgwf/co2": "^0.16.8",
7777
"array-move": "^3.0.1",
7878
"array-range": "^1.0.1",
7979
"clamp": "^1.0.1",
@@ -92,8 +92,8 @@
9292
"mixedtuplemap": "^1.0.0",
9393
"namedtuplemap": "^1.0.0",
9494
"photon-colors": "^3.3.2",
95-
"protobufjs": "^7.5.0",
96-
"query-string": "^9.1.2",
95+
"protobufjs": "^7.5.2",
96+
"query-string": "^9.2.0",
9797
"react": "^18.3.1",
9898
"react-dom": "^18.3.1",
9999
"react-intersection-observer": "^9.16.0",
@@ -154,13 +154,13 @@
154154
"husky": "^4.3.8",
155155
"jest": "^29.7.0",
156156
"jest-environment-jsdom": "^29.7.0",
157-
"jest-extended": "^4.0.2",
157+
"jest-extended": "^5.0.3",
158158
"json-loader": "^0.5.7",
159159
"local-web-server": "^5.4.0",
160160
"lockfile-lint": "^4.14.1",
161161
"mkdirp": "^3.0.1",
162162
"node-fetch": "^2.6.11",
163-
"npm-run-all2": "^8.0.1",
163+
"npm-run-all2": "^8.0.4",
164164
"open": "^10.1.2",
165165
"postcss": "^8.5.3",
166166
"postcss-loader": "^8.1.1",
@@ -171,11 +171,11 @@
171171
"stylelint": "^16.19.1",
172172
"stylelint-config-idiomatic-order": "^10.0.0",
173173
"stylelint-config-standard": "^38.0.0",
174-
"webpack": "^5.99.8",
174+
"webpack": "^5.99.9",
175175
"webpack-cli": "^6.0.1",
176176
"webpack-dev-server": "^5.2.1",
177177
"workbox-webpack-plugin": "^7.3.0",
178-
"yargs": "^17.7.2"
178+
"yargs": "^18.0.0"
179179
},
180180
"jest": {
181181
"collectCoverageFrom": [

src/actions/receive-profile.js

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import {
3838
getRelevantPagesForActiveTab,
3939
getSymbolServerUrl,
4040
getActiveTabID,
41+
getBrowserConnection,
4142
} from 'firefox-profiler/selectors';
4243
import {
4344
getSelectedTab,
@@ -397,7 +398,7 @@ export function finalizeFullProfileView(
397398
const thread = profile.threads[threadIndex];
398399
const { samples, jsAllocations, nativeAllocations } = thread;
399400
hasSamples = [samples, jsAllocations, nativeAllocations].some((table) =>
400-
hasUsefulSamples(table?.stack, thread)
401+
hasUsefulSamples(table?.stack, thread, profile.shared)
401402
);
402403
if (hasSamples) {
403404
break;
@@ -722,15 +723,20 @@ export function resymbolicateProfile(): ThunkAction<Promise<void>> {
722723
const symbolStore = getSymbolStore(
723724
dispatch,
724725
getSymbolServerUrl(getState()),
725-
null
726+
getBrowserConnection(getState())
726727
);
727728
const profile = getProfile(getState());
728729
if (!symbolStore) {
729730
throw new Error(
730731
'There was no symbol store when attempting to re-symbolicate.'
731732
);
732733
}
733-
await doSymbolicateProfile(dispatch, profile, symbolStore);
734+
await doSymbolicateProfile(
735+
dispatch,
736+
profile,
737+
symbolStore,
738+
/* ignoreCache */ true
739+
);
734740
};
735741
}
736742

@@ -793,7 +799,7 @@ export function bulkProcessSymbolicationSteps(
793799
symbolicationStepsPerThread: Map<ThreadIndex, SymbolicationStepInfo[]>
794800
): ThunkAction<void> {
795801
return (dispatch, getState) => {
796-
const { threads } = getProfile(getState());
802+
const { threads, shared } = getProfile(getState());
797803
const oldFuncToNewFuncsMaps: Map<ThreadIndex, FuncToFuncsMap> = new Map();
798804
const symbolicatedThreads = threads.map((oldThread, threadIndex) => {
799805
const symbolicationSteps = symbolicationStepsPerThread.get(threadIndex);
@@ -802,6 +808,7 @@ export function bulkProcessSymbolicationSteps(
802808
}
803809
const { thread, oldFuncToNewFuncsMap } = applySymbolicationSteps(
804810
oldThread,
811+
shared,
805812
symbolicationSteps
806813
);
807814
oldFuncToNewFuncsMaps.set(threadIndex, oldFuncToNewFuncsMap);
@@ -1004,7 +1011,8 @@ function getSymbolStore(
10041011
export async function doSymbolicateProfile(
10051012
dispatch: Dispatch,
10061013
profile: Profile,
1007-
symbolStore: SymbolStore
1014+
symbolStore: SymbolStore,
1015+
ignoreCache?: boolean
10081016
) {
10091017
dispatch(startSymbolicating());
10101018

@@ -1027,7 +1035,8 @@ export async function doSymbolicateProfile(
10271035
);
10281036
})
10291037
);
1030-
}
1038+
},
1039+
ignoreCache
10311040
);
10321041

10331042
await Promise.all(completionPromises);
@@ -1895,7 +1904,7 @@ export function changeTabFilter(tabID: TabID | null): ThunkAction<void> {
18951904
const thread = profile.threads[threadIndex];
18961905
const { samples, jsAllocations, nativeAllocations } = thread;
18971906
hasSamples = [samples, jsAllocations, nativeAllocations].some((table) =>
1898-
hasUsefulSamples(table?.stack, thread)
1907+
hasUsefulSamples(table?.stack, thread, profile.shared)
18991908
);
19001909
if (hasSamples) {
19011910
break;

src/app-logic/constants.js

Lines changed: 1 addition & 1 deletion
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

Lines changed: 2 additions & 1 deletion
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

Lines changed: 7 additions & 5 deletions
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

Lines changed: 3 additions & 1 deletion
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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,8 @@ async function processTracingEvents(
512512
// new samples on our target interval of 500us.
513513
profile.meta.interval = 0.5;
514514

515+
const stringTable = StringTable.withBackingArray(profile.shared.stringArray);
516+
515517
let profileEvents: (ProfileEvent | CpuProfileEvent)[] =
516518
(eventsByName.get('Profile'): any) || [];
517519

@@ -577,13 +579,10 @@ async function processTracingEvents(
577579
funcTable,
578580
frameTable,
579581
stackTable,
580-
stringArray,
581582
samples: samplesTable,
582583
resourceTable,
583584
} = thread;
584585

585-
const stringTable = StringTable.withBackingArray(stringArray);
586-
587586
if (nodes) {
588587
const parentMap = new Map();
589588
for (const node of nodes) {
@@ -839,7 +838,7 @@ async function extractScreenshots(
839838
screenshots[0]
840839
);
841840

842-
const stringTable = StringTable.withBackingArray(thread.stringArray);
841+
const stringTable = StringTable.withBackingArray(profile.shared.stringArray);
843842

844843
const graphicsIndex = ensureExists(profile.meta.categories).findIndex(
845844
(category) => category.name === 'Graphics'
@@ -930,6 +929,8 @@ function extractMarkers(
930929
throw new Error('No "Other" category in empty profile category list');
931930
}
932931

932+
const stringTable = StringTable.withBackingArray(profile.shared.stringArray);
933+
933934
profile.meta.markerSchema = [
934935
{
935936
name: 'EventDispatch',
@@ -996,8 +997,7 @@ function extractMarkers(
996997
event
997998
);
998999
const { thread } = threadInfo;
999-
const { markers, stringArray } = thread;
1000-
const stringTable = StringTable.withBackingArray(stringArray);
1000+
const { markers } = thread;
10011001
let argData: MixedObject | null = null;
10021002
if (event.args && typeof event.args === 'object') {
10031003
argData = (event.args: any).data || null;

src/profile-logic/import/dhat.js

Lines changed: 2 additions & 3 deletions
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

Lines changed: 20 additions & 9 deletions
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
}

0 commit comments

Comments
 (0)