Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tsc: add generated types for trace events #7817

Closed
wants to merge 18 commits into from
10 changes: 9 additions & 1 deletion lighthouse-core/computed/main-thread-tasks.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,14 @@ class MainThreadTasks {
* @param {PriorTaskData} priorTaskData
*/
static _computeRecursiveAttributableURLs(task, parentURLs, priorTaskData) {
// @ts-ignore - TODO(cjamcl) #7790 Types in transition. New types for trace events w/ no other
// changes need a little guidance.
const argsData = task.event.args.data || {};
const stackFrameURLs = (argsData.stackTrace || []).map(entry => entry.url);

/** @type {string[]} */
const stackFrameURLs = (argsData.stackTrace || [])
// @ts-ignore - TODO(cjamcl) #7790
.map(entry => entry.url);

/** @type {Array<string|undefined>} */
let taskURLs = [];
Expand All @@ -180,7 +186,9 @@ class MainThreadTasks {
case 'FunctionCall':
taskURLs = [argsData.url].concat(stackFrameURLs);
break;
// @ts-ignore - TODO(cjamcl) #7790 This type has not been generated yet.
case 'v8.compileModule':
// @ts-ignore - TODO(cjamcl) #7790 This type has not been generated yet.
taskURLs = [task.event.args.fileName].concat(stackFrameURLs);
break;
case 'TimerFire': {
Expand Down
1 change: 1 addition & 0 deletions lighthouse-core/computed/metrics/lantern-interactive.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class LanternInteractive extends LanternMetric {
return dependencyGraph.cloneWithRelationships(node => {
// Include everything that might be a long task
if (node.type === BaseNode.TYPES.CPU) {
// @ts-ignore - TODO(cjamcl) #7790
return node.event.dur > minimumCpuTaskDuration;
}

Expand Down
21 changes: 12 additions & 9 deletions lighthouse-core/computed/page-dependency-graph.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ class PageDependencyGraph {
// Skip all trace events that aren't schedulable tasks with sizable duration
if (
!TracingProcessor.isScheduleableTask(evt) ||
!TracingProcessor.isTaskWithDuration(evt) ||
!evt.dur ||
evt.dur < minimumEvtDur
) {
Expand All @@ -102,6 +103,7 @@ class PageDependencyGraph {
const children = [];
i++; // Start examining events after this one
for (
// @ts-ignore - TODO(cjamcl) #7790
const endTime = evt.ts + evt.dur;
i < traceOfTab.mainThreadEvents.length && traceOfTab.mainThreadEvents[i].ts < endTime;
i++
Expand Down Expand Up @@ -191,23 +193,29 @@ class PageDependencyGraph {
cpuNode.addDependency(minCandidate);
}

/** @type {Map<string, CPUNode>} */
/** @type {Map<number, CPUNode>} */
const timers = new Map();
for (const node of cpuNodes) {
for (const evt of node.childEvents) {
// @ts-ignore - TODO(cjamcl) #7790 Types in transition. New types for trace events w/ no
// other changes need a little guidance.
if (!evt.args.data) continue;

// @ts-ignore - TODO(cjamcl) #7790
const argsUrl = evt.args.data.url;
const stackTraceUrls = (evt.args.data.stackTrace || []).map(l => l.url).filter(Boolean);

/** @type {string[]} */
// @ts-ignore - TODO(cjamcl) #7790
const stackTraceUrls = (evt.args.data.stackTrace || [])
// @ts-ignore - TODO(cjamcl) #7790
.map(l => l.url).filter(Boolean);

switch (evt.name) {
case 'TimerInstall':
// @ts-ignore - 'TimerInstall' event means timerId exists.
timers.set(evt.args.data.timerId, node);
stackTraceUrls.forEach(url => addDependencyOnUrl(node, url));
break;
case 'TimerFire': {
// @ts-ignore - 'TimerFire' event means timerId exists.
const installer = timers.get(evt.args.data.timerId);
if (!installer) break;
installer.addDependent(node);
Expand All @@ -227,27 +235,22 @@ class PageDependencyGraph {

case 'XHRReadyStateChange':
// Only create the dependency if the request was completed
// @ts-ignore - 'XHRReadyStateChange' event means readyState is defined.
if (evt.args.data.readyState !== 4) break;

// @ts-ignore - 'XHRReadyStateChange' event means argsUrl is defined.
addDependencyOnUrl(node, argsUrl);
stackTraceUrls.forEach(url => addDependencyOnUrl(node, url));
break;

case 'FunctionCall':
case 'v8.compile':
// @ts-ignore - events mean argsUrl is defined.
addDependencyOnUrl(node, argsUrl);
break;

case 'ParseAuthorStyleSheet':
// @ts-ignore - 'ParseAuthorStyleSheet' event means styleSheetUrl is defined.
addDependencyOnUrl(node, evt.args.data.styleSheetUrl);
break;

case 'ResourceSendRequest':
// @ts-ignore - 'ResourceSendRequest' event means requestId is defined.
addDependentNetworkRequest(node, evt.args.data.requestId);
stackTraceUrls.forEach(url => addDependencyOnUrl(node, url));
break;
Expand Down
2 changes: 1 addition & 1 deletion lighthouse-core/computed/screenshots.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class Screenshots {
*/
static async compute_(trace) {
return trace.traceEvents
.filter(evt => evt.name === SCREENSHOT_TRACE_NAME)
.filter(/** @return {e is LH.TraceEvent.Screenshot} */ e => e.name === SCREENSHOT_TRACE_NAME)
.map(evt => {
return {
timestamp: evt.ts / 1000,
Expand Down
1 change: 1 addition & 0 deletions lighthouse-core/computed/speedline.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class Speedline {
// Force use of nav start as reference point for speedline
// See https://github.com/GoogleChrome/lighthouse/issues/2095
const navStart = traceOfTab.timestamps.navigationStart;
// @ts-ignore - Type incompatability with Speedline.TraceEvent.
return speedline(traceEvents, {
timeOrigin: navStart,
fastMode: true,
Expand Down
2 changes: 2 additions & 0 deletions lighthouse-core/computed/trace-of-tab.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ class TraceOfTab {
const mainFrameIds = TracingProcessor.findMainFrameIds(keyEvents);

// Filter to just events matching the frame ID for sanity
// @ts-ignore - Can't narrow types based on categories.
const frameEvents = keyEvents.filter(e => e.args.frame === mainFrameIds.frameId);

// Our navStart will be the last frame navigation in the trace
Expand Down Expand Up @@ -141,6 +142,7 @@ class TraceOfTab {
const traceEnd = trace.traceEvents.reduce((max, evt) => {
return max.ts > evt.ts ? max : evt;
});
// @ts-ignore - TODO(cjamcl) #7790
const fakeEndOfTraceEvt = {ts: traceEnd.ts + (traceEnd.dur || 0)};

/** @param {{ts: number}=} event */
Expand Down
2 changes: 1 addition & 1 deletion lighthouse-core/computed/user-timings.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class UserTimings {
return evt.name !== 'requestStart' &&
evt.name !== 'navigationStart' &&
evt.name !== 'paintNonDefaultBackgroundColor' &&
evt.args.frame === undefined;
!('frame' in evt.args);
})
.forEach(ut => {
// Mark events fall under phases R and I (or i)
Expand Down
1 change: 1 addition & 0 deletions lighthouse-core/lib/dependency-graph/cpu-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class CPUNode extends BaseNode {
* @return {number}
*/
get endTime() {
// @ts-ignore - TODO(cjamcl) #7790
return this._event.ts + this._event.dur;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ class Simulator {
? this._layoutTaskMultiplier
: this._cpuSlowdownMultiplier;
const totalDuration = Math.min(
// @ts-ignore - TODO(cjamcl) #7790
Math.round(cpuNode.event.dur / 1000 * multiplier),
DEFAULT_MAXIMUM_CPU_TASK_DURATION
);
Expand Down
14 changes: 13 additions & 1 deletion lighthouse-core/lib/lantern-trace-saver.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ function convertNodeTimingsToTrace(nodeTimings) {
const toMicroseconds = ms => baseTs + ms * 1000;

traceEvents.push(createFakeTracingStartedEvent());
// @ts-ignore - TODO(cjamcl) #7790
traceEvents.push({...createFakeTracingStartedEvent(), name: 'TracingStartedInBrowser'});

// Create a fake requestId counter
Expand Down Expand Up @@ -73,6 +74,8 @@ function convertNodeTimingsToTrace(nodeTimings) {
name: 'TracingStartedInPage',
args: {data: argsData},
dur: 0,
tdur: 0,
tts: 0,
};
}

Expand All @@ -96,6 +99,7 @@ function convertNodeTimingsToTrace(nodeTimings) {
{
...baseEvent,
ph: 'X',
// @ts-ignore - TODO(cjamcl) #7790 This type has not been generated yet.
name: 'Task',
ts: eventTs,
dur: (timing.endTime - timing.startTime) * 1000,
Expand All @@ -104,6 +108,7 @@ function convertNodeTimingsToTrace(nodeTimings) {
];

const nestedBaseTs = cpuNode.event.ts || 0;
// @ts-ignore - TODO(cjamcl) #7790
const multiplier = (timing.endTime - timing.startTime) * 1000 / cpuNode.event.dur;
// https://github.com/ChromeDevTools/devtools-frontend/blob/5429ac8a61ad4fa/front_end/timeline_model/TimelineModel.js#L1129-L1130
const netReqEvents = new Set(['ResourceSendRequest', 'ResourceFinish',
Expand All @@ -112,6 +117,7 @@ function convertNodeTimingsToTrace(nodeTimings) {
if (netReqEvents.has(event.name)) continue;
const ts = eventTs + (event.ts - nestedBaseTs) * multiplier;
const newEvent = {...event, ...{pid: baseEvent.pid, tid: baseEvent.tid}, ts};
// @ts-ignore - TODO(cjamcl) #7790
if (event.dur) newEvent.dur = event.dur * multiplier;
events.push(newEvent);
}
Expand All @@ -133,7 +139,6 @@ function convertNodeTimingsToTrace(nodeTimings) {
if (startTime === endTime) endTime += 0.3;

const requestData = {requestId: requestId.toString(), frame};
/** @type {Omit<LH.TraceEvent, 'name'|'ts'|'args'>} */
const baseRequestEvent = {...baseEvent, ph: 'I', s: 't', dur: 0};

const sendRequestData = {
Expand All @@ -157,19 +162,24 @@ function convertNodeTimingsToTrace(nodeTimings) {
decodedBodyLength: record.resourceSize,
didFail: !!record.failed,
finishTime: endTime,
encodedDataLength: record.transferSize,
};

/** @type {LH.TraceEvent[]} */
const events = [
{
...baseRequestEvent,
name: 'ResourceSendRequest',
ph: 'I',
tts: 0,
ts: toMicroseconds(startTime),
args: {data: sendRequestData},
},
{
...baseRequestEvent,
name: 'ResourceFinish',
ph: 'I',
tts: 0,
ts: toMicroseconds(endTime),
args: {data: resourceFinishData},
},
Expand All @@ -179,6 +189,8 @@ function convertNodeTimingsToTrace(nodeTimings) {
events.push({
...baseRequestEvent,
name: 'ResourceReceiveResponse',
ph: 'I',
tts: 0,
ts: toMicroseconds((startTime + endTime) / 2),
args: {data: receiveResponseData},
});
Expand Down
2 changes: 2 additions & 0 deletions lighthouse-core/lib/timing-trace-saver.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@ function generateTraceEvents(entries, threadId = 0) {
// 1) Remove 'lh:' for readability
// 2) Colons in user_timing names get special handling in traceviewer we don't want. https://goo.gl/m23Vz7
// Replace with a 'Modifier letter colon' ;)
// @ts-ignore - Allow string.
name: entry.name.replace('lh:', '').replace(/:/g, '\ua789'),
cat: 'blink.user_timing',
ts: entry.startTime * 1000,
args: {},
dur: 0,
pid: 0,
tid: threadId,
// @ts-ignore - None of the generated types happen to have a 'b' phase yet.
ph: 'b',
id: '0x' + (i++).toString(16),
};
Expand Down
23 changes: 21 additions & 2 deletions lighthouse-core/lib/traces/tracing-processor.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,15 +180,18 @@ class TraceProcessor {
const topLevelEvents = [];
// note: mainThreadEvents is already sorted by event start
for (const event of tabTrace.mainThreadEvents) {
if (!TraceProcessor.isScheduleableTask(event) || !event.dur) continue;
if (!TraceProcessor.isScheduleableTask(event)) continue;
if (!TraceProcessor.isTaskWithDuration(event)) continue;

const start = (event.ts - tabTrace.navigationStartEvt.ts) / 1000;
// @ts-ignore - TODO(cjamcl) #7790
const end = (event.ts + event.dur - tabTrace.navigationStartEvt.ts) / 1000;
if (start > endTime || end < startTime) continue;

topLevelEvents.push({
start,
end,
// @ts-ignore - TODO(cjamcl) #7790
duration: event.dur / 1000,
});
}
Expand All @@ -202,9 +205,12 @@ class TraceProcessor {
*/
static findMainFrameIds(events) {
// Prefer the newer TracingStartedInBrowser event first, if it exists
const startedInBrowserEvt = events.find(e => e.name === 'TracingStartedInBrowser');
const startedInBrowserEvt = events.find(
/** @return {e is LH.TraceEvent.TracingStartedInBrowser} */
e => e.name === 'TracingStartedInBrowser');
if (startedInBrowserEvt && startedInBrowserEvt.args.data &&
startedInBrowserEvt.args.data.frames) {
// @ts-ignore - TODO(cjamcl) #7790
const mainFrame = startedInBrowserEvt.args.data.frames.find(frame => !frame.parent);
const frameId = mainFrame && mainFrame.frame;
const pid = mainFrame && mainFrame.processId;
Expand All @@ -225,6 +231,8 @@ class TraceProcessor {
// Support legacy browser versions that do not emit TracingStartedInBrowser event.
// The first TracingStartedInPage in the trace is definitely our renderer thread of interest
// Beware: the tracingStartedInPage event can appear slightly after a navigationStart
/** @type {{args: {data: {page: string}} } & LH.TraceEvent.Base} */
// @ts-ignore - Type generation does not currently attempt retired tasks types.
const startedInPageEvt = events.find(e => e.name === 'TracingStartedInPage');
if (startedInPageEvt && startedInPageEvt.args && startedInPageEvt.args.data) {
const frameId = startedInPageEvt.args.data.page;
Expand All @@ -246,10 +254,21 @@ class TraceProcessor {
*/
static isScheduleableTask(evt) {
return evt.name === SCHEDULABLE_TASK_TITLE_LH ||
// @ts-ignore - Type generation does not currently attempt retired tasks types.
evt.name === SCHEDULABLE_TASK_TITLE_ALT1 ||
// @ts-ignore
evt.name === SCHEDULABLE_TASK_TITLE_ALT2 ||
// @ts-ignore
evt.name === SCHEDULABLE_TASK_TITLE_ALT3;
}

/**
* @param {LH.TraceEvent} evt
* @return {evt is LH.TraceEvent & {dur?: number}}
*/
static isTaskWithDuration(evt) {
return 'dur' in evt && typeof evt !== 'undefined';
}
}

/**
Expand Down
16 changes: 13 additions & 3 deletions lighthouse-core/scripts/lantern/minify-trace.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ const toplevelTaskNames = new Set([
'ThreadControllerImpl::RunTask',
]);

/**
* @param {LH.TraceEvent} evt
* @return {evt is (LH.TraceEvent.ThreadControllerImpl.DoWork |
* LH.TraceEvent.ThreadControllerImpl.RunTask |
* LH.TraceEvent.TaskQueueManager.ProcessTaskFromWorkQueue)}
*/
function isToplevelTask(evt) {
return toplevelTaskNames.has(evt.name);
}

const traceEventsToAlwaysKeep = new Set([
'Screenshot',
'TracingStartedInBrowser',
Expand Down Expand Up @@ -81,7 +91,7 @@ function filterOutUnnecessaryTasksByNameAndDuration(events) {
const {pid} = TracingProcessor.findMainFrameIds(events);

return events.filter(evt => {
if (toplevelTaskNames.has(evt.name) && evt.dur < 1000) return false;
if (isToplevelTask(evt) && (evt.dur || 0) < 1000) return false;
if (evt.pid === pid && traceEventsToKeepInProcess.has(evt.name)) return true;
return traceEventsToAlwaysKeep.has(evt.name);
});
Expand All @@ -93,8 +103,8 @@ function filterOutUnnecessaryTasksByNameAndDuration(events) {
*/
function filterOutOrphanedTasks(events) {
const toplevelRanges = events
.filter(evt => toplevelTaskNames.has(evt.name))
.map(evt => [evt.ts, evt.ts + evt.dur]);
.filter(isToplevelTask)
.map(evt => [evt.ts, evt.ts + (evt.dur || 0)]);

/** @param {LH.TraceEvent} e */
const isInToplevelTask = e => toplevelRanges.some(([start, end]) => e.ts >= start && e.ts <= end);
Expand Down
Loading