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(metrics): support LCP in all frames for devtools throttling #11701

Merged
merged 11 commits into from
Nov 26, 2020

Conversation

adamraine
Copy link
Member

Part 1a of the Framehole implementation plan for LCP events.

@adamraine adamraine requested a review from a team as a code owner November 23, 2020 21:46
@adamraine adamraine requested review from connorjclark and removed request for a team November 23, 2020 21:46
@google-cla google-cla bot added the cla: yes label Nov 23, 2020
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.

thanks @adamraine :)

@adamraine
Copy link
Member Author

@patrickhulce @connorjclark Just a heads up, I'm gonna bring up another PR to merge into this one which supports CLS from all frames.

@connorjclark
Copy link
Collaborator

connorjclark commented Nov 25, 2020

can we keep that as a separate PR (and not merge into this branch)?

@adamraine
Copy link
Member Author

can we keep that as a separate PR (and not merge into this branch)?

Sure

Copy link
Collaborator

@connorjclark connorjclark left a comment

Choose a reason for hiding this comment

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

LGTM. Patrick, wdyt?

lighthouse-core/lib/tracehouse/trace-processor.js Outdated Show resolved Hide resolved
@@ -0,0 +1,55 @@
[
Copy link
Collaborator

Choose a reason for hiding this comment

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

muuuuuch better :) thanks!

Co-authored-by: Patrick Hulce <patrick.hulce@gmail.com>
@adamraine
Copy link
Member Author

@patrickhulce @connorjclark Do we need to wait for v7 to merge this?

@patrickhulce
Copy link
Collaborator

I think the opposite @adamraine we really want to get this in for the last 6.x

@adamraine adamraine merged commit bca4e21 into master Nov 26, 2020
@adamraine adamraine deleted the lcp-all-frames-metrics branch November 26, 2020 01:26
Copy link
Member

@paulirish paulirish left a comment

Choose a reason for hiding this comment

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

noticed a few things that might matter to the calculation accuracy under certain conditions. @adamraine lemme know if you've already spotted this stuff.

const lcpAllFramesEvt = this.computeValidLCP({
candidateEventName: 'NavStartToLargestContentfulPaint::Candidate::AllFrames::UKM',
invalidateEventName: 'NavStartToLargestContentfulPaint::Invalidate::AllFrames::UKM',
events: keyEvents,
Copy link
Member

Choose a reason for hiding this comment

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

I think there's an edge case this may not account for.

The situation would be theverge loading in one tab while nytimes is loading in another tab. keyEvents is for all processes and so I think the resulting LCP-AF would merge together both tabs.

I'm not sure this is the case, but it looks like it...

the trace event lives in browser/ so my guess is it's emitted on the browser process. it does contain a mainframeid however. and we have findMainFrameIds, so I think we can filter the trace events to be just the mainframeid ones we care about.

Copy link
Collaborator

@patrickhulce patrickhulce Nov 30, 2020

Choose a reason for hiding this comment

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

The situation would be theverge loading in one tab while nytimes is loading in another tab. keyEvents is for all processes and so I think the resulting LCP-AF would merge together both tabs.

I jumped to this as well, but I tried on half a dozen pages unsuccessfully 😅 Is the "looks like it" from looking at the code in Chromium or a case that you observed?

Copy link
Member Author

Choose a reason for hiding this comment

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

What would a trace like this look like?

Using the performance panel, I am able to produce a trace with LCP-AF events with two different values for main_frame_tree_node_id.

Copy link
Member

Choose a reason for hiding this comment

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

hmm i just got one.

trace: https://gist.github.com/paulirish/ebfeeac8d2a243042041ab4e1bc87c7f

image

repro:

  • chrome-debug
  • open devtools
  • open another chrome window, and make sure both windows are visible (not occluding the other)
  • put example.com in window 1's omnibox and paulirish.com in window 2's.
  • start perf panel recording
  • hit enter on both omniboxes
  • wait a bit and stop recording

Copy link
Collaborator

Choose a reason for hiding this comment

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

and make sure both windows are visible (not occluding the other)

🤦 this is almost definitely what I forgot

Copy link
Member Author

Choose a reason for hiding this comment

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

@paulirish findMainFrameIds doesn't return a node id, is there another way to get the main frame node id?

Copy link
Member

Choose a reason for hiding this comment

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

@paulirish findMainFrameIds doesn't return a node id, is there another way to get the main frame node id?

good question.... doing this would certainly be easier if main_frame_tree_node_id was instead main_frame_tree_frame_id but alas. Hmmmm.. we'll have to do some hunting.

@npm1 do you currently make use of main_frame_tree_frame_id to filter things? as of now, we don't have any mapping between frames/frametrees to node ids, so before we invent one, I'm curious if something already exists.

@@ -543,6 +586,7 @@ class TraceProcessor {
firstContentfulPaint: frameTimings.timings.firstContentfulPaint,
firstMeaningfulPaint: frameTimings.timings.firstMeaningfulPaint,
largestContentfulPaint: frameTimings.timings.largestContentfulPaint,
largestContentfulPaintAllFrames: maybeGetTiming(lcpAllFramesEvt && lcpAllFramesEvt.ts),
Copy link
Member

Choose a reason for hiding this comment

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

something i spotted while looking at the trace event.....

https://source.chromium.org/chromium/chromium/src/+/master:chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.cc;l=1091-1095;drc=2b934611e4e480b7121488288f97ef27e0950e2a

It seems like sometimes the trace event carries a specific timestamp.. so i think we'd want to use that rather than the event's ts.

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 can't seem to find the timestamp you're referring to. There is only a durationInMilliseconds property.

Copy link
Collaborator

Choose a reason for hiding this comment

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

my silly project agrees with @adamraine https://github.com/connorjclark/chrome-trace-events-tsc/blob/master/dist/lh-trace-events.d.ts#L487 (altho I only used one recent trace from cnn.com)

Copy link
Member

Choose a reason for hiding this comment

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

@connorjclark thanks for checking. yeah you can see in the .cc source i linked that there are two ways the LCP trace event are emitted. I haven't really tracked back the conditions that determine which of the two are used.. but.. we'd need enough traces to get both of em for yr project to catch it, i guess. no big deal though.

@adamraine ah yeah.. actually the durationInMilliseconds prop is exactly what i was talking about. (I hadn't clicked through on DataAsTraceValue() till now).

But yes it looks vaguely like: if durationInMilliseconds is being provided, it should be used rather than the ts of the event. @npm1 is that what's going on?

Copy link
Collaborator

Choose a reason for hiding this comment

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

if durationInMilliseconds is being provided, it should be used rather than the ts of the event.

👀 at our time origin complexities, oh boy 😅

Copy link

Choose a reason for hiding this comment

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

Correct, durationInMilliseconds is the LCP value. Sorry for the confusion, maybe there was a way to have the trace event's timestamp be the LCP itself? It's probably a bit late to fix.

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

Successfully merging this pull request may close these issues.

6 participants