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

Improve reliability of finding navStart #1895

Merged
merged 2 commits into from
Mar 24, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 22 additions & 16 deletions lighthouse-core/gather/computed/trace-of-tab.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ const ComputedArtifact = require('./computed-artifact');
const log = require('../../lib/log');

class TraceOfTab extends ComputedArtifact {

get name() {
return 'TraceOfTab';
}
Expand All @@ -43,30 +42,35 @@ class TraceOfTab extends ComputedArtifact {
*/
compute_(trace) {
// Parse the trace for our key events and sort them by timestamp.
const keyEvents = trace.traceEvents.filter(e => {
return e.cat.includes('blink.user_timing') || e.cat.includes('loading') ||
const keyEvents = trace.traceEvents
.filter(e => {
return e.cat.includes('blink.user_timing') ||
e.cat.includes('loading') ||
e.name === 'TracingStartedInPage';
}).sort((event0, event1) => event0.ts - event1.ts);
})
.sort((event0, event1) => event0.ts - event1.ts);

// The first TracingStartedInPage in the trace is definitely our renderer thread of interest
// Beware: the tracingStartedInPage event can appear slightly after a navigationStart
const startedInPageEvt = keyEvents.find(e => e.name === 'TracingStartedInPage');
// Filter to just events matching the frame ID for sanity
const frameEvents = keyEvents.filter(e => e.args.frame === startedInPageEvt.args.data.page);

// Our navStart will be the last frame navigation in the trace
const navigationStart = frameEvents.filter(e => e.name === 'navigationStart').pop();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we throw here if it's undefined so we get slightly more friendly error?


// Find our first paint of this frame
const firstPaint = frameEvents.find(e => e.name === 'firstPaint');
// Our navStart will be the latest one before fP.
const navigationStart = frameEvents.filter(e =>
e.name === 'navigationStart' && e.ts < firstPaint.ts).pop();
const firstPaint = frameEvents.find(e => e.name === 'firstPaint' && e.ts > navigationStart.ts);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

strict > and not >=?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah. if FP was at the same time, i would have BIG concerns about the trace and i'd need to debug it. because that's definitely not correct.


// FCP will follow at/after the FP
const firstContentfulPaint = frameEvents.find(e =>
e.name === 'firstContentfulPaint' && e.ts >= firstPaint.ts);
const firstContentfulPaint = frameEvents.find(
e => e.name === 'firstContentfulPaint' && e.ts > navigationStart.ts
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any significance of dropping the e.ts >= firstPaint.ts and using relative to navigationStart instead?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we were using FP as the reference event before. Honestly this line could been asking for > navStart rather than FP, but it was just all FP for consistency.

);

// fMP will follow at/after the FP
let firstMeaningfulPaint = frameEvents.find(e =>
e.name === 'firstMeaningfulPaint' && e.ts >= firstPaint.ts);
let firstMeaningfulPaint = frameEvents.find(
e => e.name === 'firstMeaningfulPaint' && e.ts > navigationStart.ts
);

// If there was no firstMeaningfulPaint event found in the trace, the network idle detection
// may have not been triggered before Lighthouse finished tracing.
Expand All @@ -83,17 +87,19 @@ class TraceOfTab extends ComputedArtifact {
}

// subset all trace events to just our tab's process (incl threads other than main)
const processEvents = trace.traceEvents.filter(e => {
return e.pid === startedInPageEvt.pid;
}).sort((event0, event1) => event0.ts - event1.ts);
const processEvents = trace.traceEvents
.filter(e => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: inline

return e.pid === startedInPageEvt.pid;
})
.sort((event0, event1) => event0.ts - event1.ts);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this formatting change makes the diff hard to read :P no difference, right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

correct


return {
processEvents,
startedInPageEvt: startedInPageEvt,
navigationStartEvt: navigationStart,
firstPaintEvt: firstPaint,
firstContentfulPaintEvt: firstContentfulPaint,
firstMeaningfulPaintEvt: firstMeaningfulPaint
firstMeaningfulPaintEvt: firstMeaningfulPaint,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:D

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I started using https://github.com/prettier/prettier on demand in this PR. I'm already in love.

};
}
}
Expand Down
39 changes: 14 additions & 25 deletions lighthouse-core/lib/traces/pwmetrics-events.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,25 +121,15 @@ class Metrics {
}

/**
* Getter for our navigationStart trace event
* Get the full trace event for our navigationStart
* @param {!Array<{ts: number, id: string, name: string}>} metrics
*/
getNavigationStartEvt() {
if (!this._navigationStartEvt) {
const filteredEvents = this._traceEvents.filter(e => {
return e.name === 'TracingStartedInPage' || e.cat === 'blink.user_timing';
});

const tracingStartedEvt = filteredEvents.filter(e => e.name === 'TracingStartedInPage')[0];
const navigationStartEvt = filteredEvents.filter(e => {
return e.name === 'navigationStart' &&
e.pid === tracingStartedEvt.pid && e.tid === tracingStartedEvt.tid;
})[0];
this._navigationStartEvt = navigationStartEvt;
}
return this._navigationStartEvt;
identifyNavigationStartEvt(metrics) {
const navStartTs = metrics.find(e => e.id === 'navstart').ts;
this._navigationStartEvt = this._traceEvents
.find(e => e.name === 'navigationStart' && e.ts === navStartTs);
}


/**
* Constructs performance.measure trace events, which have start/end events as follows:
* { "pid": 89922,"tid":1295,"ts":77176783452,"ph":"b","cat":"blink.user_timing","name":"innermeasure","args":{},"tts":1257886,"id":"0xe66c67"}
Expand All @@ -148,19 +138,19 @@ class Metrics {
* @param {{ts: number, id: string, name: string}} navStart
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delete navStart from jsdoc

* @return {!Array} Pair of trace events (start/end)
*/
synthesizeEventPair(metric, navStart) {
synthesizeEventPair(metric) {
// We'll masquerade our fake events to look mostly like navigationStart
const eventBase = {
pid: this.getNavigationStartEvt().pid,
tid: this.getNavigationStartEvt().tid,
pid: this._navigationStartEvt.pid,
tid: this._navigationStartEvt.tid,
cat: 'blink.user_timing',
name: metric.name,
args: {},
// randomized id is same for the pair
id: `0x${((Math.random() * 1000000) | 0).toString(16)}`
};
const fakeMeasureStartEvent = Object.assign({}, eventBase, {
ts: navStart.ts,
ts: this._navigationStartEvt.ts,
ph: 'b'
});
const fakeMeasureEndEvent = Object.assign({}, eventBase, {
Expand All @@ -181,10 +171,9 @@ class Metrics {
return [];
}

// confirm our navStart's correctly match
const navStartEvt = metrics.find(e => e.id === 'navstart');
if (!navStartEvt || this.getNavigationStartEvt().ts !== navStartEvt.ts) {
log.error('pwmetrics-events', 'Reference navigationStart doesn\'t match fMP\'s navStart');
this.identifyNavigationStartEvt(metrics);
if (!this._navigationStartEvt) {
log.error('pwmetrics-events', 'Reference navigationStart not found');
return [];
}

Expand All @@ -197,7 +186,7 @@ class Metrics {
return;
}
log.verbose('pwmetrics-events', `Sythesizing trace events for ${metric.name}`);
fakeEvents.push(...this.synthesizeEventPair(metric, navStartEvt));
fakeEvents.push(...this.synthesizeEventPair(metric));
});
return fakeEvents;
}
Expand Down
Loading