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

core(cls-all-frames): use weighted score from trace #12034

Merged
merged 10 commits into from
Feb 3, 2021

Conversation

adamraine
Copy link
Member

@adamraine adamraine commented Feb 1, 2021

Closes #12023

CLS-AF will be calculated with weighted_score_delta instead of score.

I'm not planning on merging until after weighted score is merged in M89:
https://bugs.chromium.org/p/chromium/issues/detail?id=1173139

Patch is not getting merged into M89, not waiting for M90 to merge this.

@adamraine adamraine requested a review from a team as a code owner February 1, 2021 21:13
@adamraine adamraine requested review from patrickhulce and removed request for a team February 1, 2021 21:13
@google-cla google-cla bot added the cla: yes label Feb 1, 2021
const trace = require('../../fixtures/traces/frame-metrics-m89.json');
const devtoolsLog = require('../../fixtures/traces/frame-metrics-m89.devtools.log.json');
const trace = require('../../fixtures/traces/frame-metrics-m90.json');
const devtoolsLog = require('../../fixtures/traces/frame-metrics-m90.devtools.log.json');
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 tried to avoid changing our expectations for LCP-AF and FCP-AF in any tests that I could. This is the only place I couldn't.

@@ -0,0 +1,242 @@
{
Copy link
Member Author

Choose a reason for hiding this comment

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

Keeping frame-metrics-m89.json around so we don't have to change expectations for LCP-AF and FCP-AF everywhere.

@@ -3,7 +3,7 @@
exports[`Performance: metrics evaluates valid input (with lcp from all frames) correctly 1`] = `
Object {
"cumulativeLayoutShift": 0.0011656245471340055,
"cumulativeLayoutShiftAllFrames": 0.4591700003057729,
"cumulativeLayoutShiftAllFrames": undefined,
Copy link
Member Author

Choose a reason for hiding this comment

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

This snapshot is using the old trace without the weighted score, so CLS-AF is undefined.

Copy link
Collaborator

@patrickhulce patrickhulce left a comment

Choose a reason for hiding this comment

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

LGTM just the throw decision outstanding I think :)

* @param {LH.TraceEvent} event
* @return {event is LayoutShiftEvent}
*/
static isLayoutShiftEvent(event) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: isValidLayoutShiftEvent or something? I wouldn't expect all of the validation and throw logic in a simple check

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'm leaving this as is because the validation and throw logic are removed.

// Weighted score was added to the trace in m89:
// https://bugs.chromium.org/p/chromium/issues/detail?id=1173139
if (typeof event.args.data.weighted_score_delta !== 'number') {
throw new LHError(
Copy link
Collaborator

Choose a reason for hiding this comment

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

should this fallback to score? seems like there's still some value in seeing if the all frames version and main-frame version are different. I understand the difficulty of figuring out which CLS values are valid, but seems like we're going to have to do that anyway with a mix of LH versions in the same month.

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'm good with doing a fallback and replacing this with a log warning for now.

I'm just worried that the fallback doesn't make sense in the long run. Once we get through the churn of different LH and Chrome versions I would like to remove the fallback.

Copy link
Collaborator

Choose a reason for hiding this comment

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

SG, can throw a FIXME: remove after XX on there :)

lighthouse-core/test/audits/metrics-test.js Show resolved Hide resolved
@adamraine
Copy link
Member Author

@patrickhulce sorry to increase the scope a bit, but I noticed another pretty big error while picking through some HTTPArchive results. Many of the sites had a CLS-AF smaller than CLS which doesn't make sense since extra frames should only add to CLS.

Turns out I didn't add the correct had_recent_input logic from the main frame CLS:

// Chromium will set `had_recent_input` if there was recent user input, which
// skips shift events from contributing to CLS. This flag is also set when Lighthouse changes
// the emulation size. This consistently results in the first few shift event always being
// ignored for CLS. Since we don't expect any user input, we add the score of these
// shift events to CLS.
// See https://bugs.chromium.org/p/chromium/issues/detail?id=1094974.
for (let i = 0; i < traceOfTab.mainThreadEvents.length; i++) {
const evt = traceOfTab.mainThreadEvents[i];
if (evt.name === 'LayoutShift' && evt.args && evt.args.data && evt.args.data.is_main_frame) {
if (!evt.args.data.had_recent_input) break;
if (typeof evt.args.data.score !== 'number') continue;
cumulativeLayoutShift += evt.args.data.score;
}
}

I added changes in this PR to address this error.

// ignored for CLS. Since we don't expect any user input, we add the score of these
// shift events to CLS.
// See https://bugs.chromium.org/p/chromium/issues/detail?id=1094974.
for (const event of layoutShiftEvents) {
Copy link
Collaborator

@connorjclark connorjclark Feb 2, 2021

Choose a reason for hiding this comment

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

Some more comments here would be useful. Is this accurate?

We set the first initial events that appear as had_recent_input=true to false, up until the first time had_recent_input=false appears. This ignores the incorrect inputs that are an artifact of Lighthouse changing the viewport size, and keeps any inputs that appear later in the page load (as a result of a puppeteer script controlling the page).

Copy link
Collaborator

Choose a reason for hiding this comment

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

does the logic here need to be more complex now in a multi-frame world? how does had_recent_input affect subframes when their viewports are resized from js? should those actually be counted? if so, the "had_recent_input" name is really starting to stretch 😆

Copy link
Member

@brendankenny brendankenny Feb 2, 2021

Choose a reason for hiding this comment

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

+1 to everything above, plus should we be doing this fixup in trace-of-tab (well, trace-processor, actually)? Or not altering the original trace events and doing it on a copy of the LayoutShift events in each of these audits...otherwise the state of early LayoutShift events depends on what other audits/computed artifacts have already run (e.g. an ads plugin CLS audit that either has to know about this issue or has to only run after the perf audits to get the numbers right)

return /** @type {number} */ (e.args.data.score);
if (e.args.data.had_recent_input) return 0;

// FIXME: remove after 89 hits stable
Copy link
Collaborator

Choose a reason for hiding this comment

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

@paulirish likes COMPAT

Copy link
Collaborator

@patrickhulce patrickhulce Feb 2, 2021

Choose a reason for hiding this comment

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

yeah I guess this is more COMPAT than FIXME, sorry for the bad suggestion @adamraine

Copy link
Collaborator

@patrickhulce patrickhulce left a comment

Choose a reason for hiding this comment

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

Nice catch I completely forgot about that workaround too! We should probably share the computation of CLS based on a sequence of layoutshift events now that it's sufficiently complicated though. How disappointed would you be to move that fix and a sharing refactor to a new PR? Anytime there's logic requiring a comment that large, feels like it shouldn't be duplicated :)

Unrelated but important to note that we won't really have a similar workaround ability for FR :/ we'll cross that bridge when we get there I suppose.

// ignored for CLS. Since we don't expect any user input, we add the score of these
// shift events to CLS.
// See https://bugs.chromium.org/p/chromium/issues/detail?id=1094974.
for (const event of layoutShiftEvents) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

does the logic here need to be more complex now in a multi-frame world? how does had_recent_input affect subframes when their viewports are resized from js? should those actually be counted? if so, the "had_recent_input" name is really starting to stretch 😆

@adamraine
Copy link
Member Author

Ok, moving the had_recent_input logic to a separate PR.

@adamraine
Copy link
Member Author

Another update: release manager would prefer the weighted score change stay in M90:
https://bugs.chromium.org/p/chromium/issues/detail?id=1173139#c4

I don't think this is a major issue for us, just means we need to adjust some comments and stuff here.

Copy link
Collaborator

@patrickhulce patrickhulce left a comment

Choose a reason for hiding this comment

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

still LGTM thanks for punting the other input fix :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

All frame CLS should use weighted score to account for frame size
5 participants