Skip to content

Commit 3d1ca29

Browse files
committed
Inline source/line resolution in line-timings hot loop
getStackLineInfo runs once per stack in the stack table, which can mean hundreds of thousands of iterations on large profiles. Calling getOriginalPositionForFrame in that loop allocated a fresh {source, line, column} object per stack and always resolved the line (and column) even though the line is only used when the stack's source matches the source view, and the column is never used here. Inline the 3-tier source-map fallback so we drop the per-stack allocation, skip the column entirely, and defer the line lookup until matchesSource is true. Apply the same inlining to getTotalLineTimingsForCallNode, which has the same shape and only needs the line. Measured on a large profile: getStackLineInfo went from ~373ms back to ~199ms.
1 parent 4bd48b9 commit 3d1ca29

1 file changed

Lines changed: 44 additions & 20 deletions

File tree

src/profile-logic/line-timings.ts

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import type {
1515
SourceLocationTable,
1616
} from 'firefox-profiler/types';
1717
import { SetCollectionBuilder } from 'firefox-profiler/utils/set-collection';
18-
import { getOriginalPositionForFrame } from './profile-data';
1918

2019
/**
2120
* For each stack in `stackTable`, and one specific source file, compute the
@@ -62,20 +61,38 @@ export function getStackLineInfo(
6261

6362
const frame = stackTable.frame[stackIndex];
6463
const func = frameTable.func[frame];
65-
const { source: sourceIndexOfThisStack, line: selfLineFromMapping } =
66-
getOriginalPositionForFrame(
67-
frame,
68-
func,
69-
frameTable,
70-
funcTable,
71-
sourceLocationTable
72-
);
64+
65+
// Inlined source resolution from getOriginalPositionForFrame. We avoid
66+
// its per-stack {source, line, column} allocation, skip resolving the
67+
// column entirely, and defer the line lookup until we know the source
68+
// matches.
69+
const frameOriginalLocationIdx = frameTable.originalLocation[frame];
70+
const funcOriginalLocationIdx = funcTable.originalLocation[func];
71+
let sourceIndexOfThisStack;
72+
if (frameOriginalLocationIdx !== null) {
73+
sourceIndexOfThisStack =
74+
sourceLocationTable.source[frameOriginalLocationIdx];
75+
} else if (funcOriginalLocationIdx !== null) {
76+
sourceIndexOfThisStack =
77+
sourceLocationTable.source[funcOriginalLocationIdx];
78+
} else {
79+
sourceIndexOfThisStack = funcTable.source[func];
80+
}
7381

7482
const matchesSource = sourceIndexOfThisStack === sourceViewSourceIndex;
7583
if (prefixLineSet === -1 && !matchesSource) {
7684
stackIndexToLineSetIndex[stackIndex] = -1;
7785
} else {
78-
const selfLineOrNull = matchesSource ? selfLineFromMapping : null;
86+
let selfLineOrNull: number | null = null;
87+
if (matchesSource) {
88+
if (frameOriginalLocationIdx !== null) {
89+
selfLineOrNull = sourceLocationTable.line[frameOriginalLocationIdx];
90+
} else if (funcOriginalLocationIdx !== null) {
91+
selfLineOrNull = sourceLocationTable.line[funcOriginalLocationIdx];
92+
} else {
93+
selfLineOrNull = frameTable.line[frame] ?? funcTable.lineNumber[func];
94+
}
95+
}
7996

8097
stackIndexToLineSetIndex[stackIndex] = builder.extend(
8198
prefixLineSet !== -1 ? prefixLineSet : null,
@@ -193,17 +210,24 @@ export function getTotalLineTimingsForCallNode(
193210
continue;
194211
}
195212

196-
// Resolve in the same coordinate space as the source view: helper returns
197-
// a source-mapped line when available, otherwise the frame's compiled
198-
// line, otherwise the func's compiled line.
213+
// Resolve in the same coordinate space as the source view: prefer the
214+
// source-mapped line, otherwise the frame's compiled line, otherwise the
215+
// func's compiled line. Inlined from getOriginalPositionForFrame to avoid
216+
// the per-sample object allocation.
199217
const funcIndex = frameTable.func[callNodeFrame];
200-
const { line: frameLine } = getOriginalPositionForFrame(
201-
callNodeFrame,
202-
funcIndex,
203-
frameTable,
204-
funcTable,
205-
sourceLocationTable
206-
);
218+
const frameOriginalLocationIdx = frameTable.originalLocation[callNodeFrame];
219+
let frameLine: number | null;
220+
if (frameOriginalLocationIdx !== null) {
221+
frameLine = sourceLocationTable.line[frameOriginalLocationIdx];
222+
} else {
223+
const funcOriginalLocationIdx = funcTable.originalLocation[funcIndex];
224+
if (funcOriginalLocationIdx !== null) {
225+
frameLine = sourceLocationTable.line[funcOriginalLocationIdx];
226+
} else {
227+
frameLine =
228+
frameTable.line[callNodeFrame] ?? funcTable.lineNumber[funcIndex];
229+
}
230+
}
207231
const line = frameLine !== null ? frameLine : funcLine;
208232
if (line === null) {
209233
continue;

0 commit comments

Comments
 (0)