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(lantern): add edges from initiatorRequest when there are duplicate records #10097

Merged
merged 22 commits into from
Apr 2, 2020

Conversation

warrengm
Copy link
Contributor

@warrengm warrengm commented Dec 11, 2019

This PR fixes some missing edges in the lantern simulation graph where a network record won't depend on its initiatorRequest if there are multiple records for the initiator. In practice I think this mainly affects cases where a script is prefetched which in turn causes multiple records and prevents connections to its initiated requests.

I fixed this by:

  1. In network-recorder.js: make sure that initiatorRequest points to the proper script request, not the prefetch record.
  2. In page-dependency-graph.js: fall back to the initiator request (when present) rather than the root node if the parent candidate is ambiguous.

The main changes to lantern are:

Metric                    p50 (% Error)        p90 (% Error)        p95 (% Error)       
optimisticFCP             16.9% ↔  0.0%        45.0% ↓  2.8%        54.0% ↓↓ 7.5%       
pessimisticFCP            16.4% ↔  0.2%        47.8% ↓  1.9%        73.6% ↔  0.0%       
roughEstimateOfFCP        16.2% ↔  0.0%        45.0% ↓  2.6%        61.0% ↔  0.0%       
optimisticFMP             18.1% ↔  0.0%        50.9% ↓  2.3%        62.5% ↓  4.8%       
pessimisticFMP            17.6% ↑  0.8%        52.9% ↔  0.0%        69.5% ↓  5.7%       
roughEstimateOfFMP        16.4% ↔  0.0%        49.6% ↔  0.2%        57.7% ↔  0.2%       
optimisticTTFCPUI         22.2% ↔  0.0%        62.0% ↑  4.3%        92.1% ↑  4.3%       
pessimisticTTFCPUI        20.7% ↓  0.5%        73.2% ↔  0.0%        122.4% ↓  3.6%      
roughEstimateOfTTFCPUI    22.2% ↑  0.9%        54.5% ↑  0.8%        92.1% ↑↑ 17.1%      
optimisticTTI             28.9% ↓  1.3%        56.7% ↓  1.6%        63.4% ↓  3.0%       
pessimisticTTI            20.6% ↔  0.1%        79.9% ↔  0.0%        135.3% ↔  1.3%      
roughEstimateOfTTI        23.3% ↔  0.0%        58.5% ↑  2.2%        110.3% ↑  1.4%      
optimisticSI              65.0% ↔  0.0%        83.7% ↔  0.0%        90.9% ↔  0.0%       
pessimisticSI             44.8% ↔  0.0%        84.4% ↔  0.0%        89.7% ↔  0.0%       
roughEstimateOfSI         36.0% ↑  1.1%        75.0% ↔  0.0%        82.9% ↔  0.2%       
optimisticLCP             NaN% ↓  NaN%         NaN% ↓  NaN%         NaN% ↓  NaN%        
pessimisticLCP            NaN% ↓  NaN%         NaN% ↓  NaN%         NaN% ↓  NaN%        
roughEstimateOfLCP        NaN% ↓  NaN%         NaN% ↓  NaN%         NaN% ↓  NaN%        

 ------- Fixes Summary -------
FCP on http://www.cnet.com/ - 3046 (real) 2859 (cur) 2162 (prev)
FCP on http://www.rakuten.ne.jp/ - 6988 (real) 3941 (cur) 2750 (prev)
TTFCPUI on http://www.metrolyrics.com/ - 27321 (real) 34647 (cur) 39302 (prev)
TTFCPUI on http://www.4399.com/ - 5413 (real) 4229 (cur) 3585 (prev)

 ------- Regression Summary -------
TTFCPUI on http://www.deviantart.com/ - 11309 (real) 21719 (cur) 9961 (prev)
SI on http://www.pdfqueen.com/ - 2421 (real) 3428 (cur) 2730 (prev)
TTFCPUI on http://www.pdfqueen.com/ - 3698 (real) 4727 (cur) 3803 (prev)
TTI on http://www.pdfqueen.com/ - 3698 (real) 4820 (cur) 3953 (prev)

 ------- Bucket Summary -------
Good:      242   ↓  3
OK:        185   ↑  6
Bad:       67    ↓  3

 ------- % Error Summary -------
p50:       27.4% ↑  0.3%
p90:       35.0% ↓↓ 17.9%
p95:       37.7% ↓↓ 37.3%

In pubads audits we duct taped this issue with googleads/publisher-ads-lighthouse-plugin#174.

@warrengm warrengm changed the title core(lantern): Guarantee edges from initiatorRequest when there are duplicate records core(lantern): Add edges from initiatorRequest when there are duplicate records Dec 11, 2019
@warrengm
Copy link
Contributor Author

Thinking this a bit more, I think this can be generalized a bit further (for example, when iframes are prefetched) by making sure that lighthouse doesn't choose prefetch request as initiators (in network-recorder.js or adding links to frames in page-dependency-graph.js)

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 a ton @warrengm, great find!! 👏 👏 💯

@@ -0,0 +1,851 @@
[
{
"method": "Page.lifecycleEvent",
Copy link
Collaborator

Choose a reason for hiding this comment

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

would you mind running this through our ./lighthouse-core/scripts/lantern/minify-devtoolslog.js script to prune some of the unnecessary stuff?

Copy link
Collaborator

Choose a reason for hiding this comment

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

did you get a chance to give that script a whirl?

if (!possiblePrefetchRecords.has(record.url)) {
possiblePrefetchRecords.set(record.url, record);
}
} else if (!typedRecords.has(record.url)) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I wonder if we should start taking the same approach here as in page-dependency-graph and not set the initiator if it was ambiguous on the typedRecords

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Possibly. I can take a look in a follow-up PR.

I did look a bit into resolving ambiguities in page-dependency-graph, and they all seemed to increase the errors in simulation. Even when I did:

const parentCandidates = (networkNodeOutput.urlToNodeMap.get(initiator) || [])
    .filter(candidate => candidate.startTime < node.startTime);

Though there are cases that I would expect to be resolvable. For example, sometimes gpt.js is loaded inside of the top window and inside of iframes. But, again, some of the naive filters I wrote increased the amount of error in simulation so more work would be needed to investigate. (Which is out of scope of this PR but I could look into at some point)

lighthouse-core/lib/network-recorder.js Outdated Show resolved Hide resolved
lighthouse-core/lib/network-recorder.js Outdated Show resolved Hide resolved
// Only add the initiator relationship if the initiator is unambiguous
const parent = parentCandidates.length === 1 ? parentCandidates[0] : rootNode;
const parent = parentCandidates.length === 1 ? parentCandidates[0] : directInitiatorNode;
Copy link
Collaborator

Choose a reason for hiding this comment

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

we probably should have been doing this all along but now that we're selecting initiators that will be later in load can we add a quick check that the request started after the parent?

@@ -353,7 +359,10 @@ class NetworkRecorder extends EventEmitter {
const initiatorURL = record.initiator.url || (stackFrames[0] && stackFrames[0].url);
// If we were redirected to this request, our initiator is that redirect, otherwise, it's the
// initiator provided by the protocol. See https://github.com/GoogleChrome/lighthouse/pull/7352/
const initiator = record.redirectSource || recordsByURL.get(initiatorURL);
const initiator = record.redirectSource ||
Copy link
Collaborator

Choose a reason for hiding this comment

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

should probably do that same time check about starting after the initiator here too

patrickhulce
patrickhulce previously approved these changes Dec 13, 2019
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 thanks very much warren! looks awesome 😍 just a few minor nits

lighthouse-core/lib/network-recorder.js Outdated Show resolved Hide resolved
lighthouse-core/lib/network-recorder.js Outdated Show resolved Hide resolved
lighthouse-core/lib/network-recorder.js Outdated Show resolved Hide resolved
@@ -340,20 +371,26 @@ class NetworkRecorder extends EventEmitter {
// get out the list of records & filter out invalid records
const records = networkRecorder.getRecords().filter(record => record.isValid);

// create a map of all the records by URL to link up initiator
const recordsByURL = new Map();
// The initiator is unlikely to be a prefetch record which have type 'Other'
Copy link
Collaborator

Choose a reason for hiding this comment

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

❤️

@@ -0,0 +1,851 @@
[
{
"method": "Page.lifecycleEvent",
Copy link
Collaborator

Choose a reason for hiding this comment

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

did you get a chance to give that script a whirl?

@warrengm warrengm requested a review from a team as a code owner March 4, 2020 19:57
@warrengm warrengm changed the title core(lantern): Add edges from initiatorRequest when there are duplicate records core(lantern): add edges from initiatorRequest when there are duplicate records Mar 4, 2020
@warrengm
Copy link
Contributor Author

warrengm commented Mar 4, 2020

Hi @patrickhulce, I think this is ready to merge now!

I didn't notice that my branch was behind master and then went on some travels--but I made time to finish it up today.

@patrickhulce patrickhulce assigned patrickhulce and unassigned warrengm Mar 4, 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.

LGTM! 🎉

}
}

return candidates.length ? candidates[0] : null;
Copy link
Collaborator

Choose a reason for hiding this comment

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

friendly bump on this, if you're already thought this through a simple explanation is all I'm lookin for here :)

@patrickhulce
Copy link
Collaborator

oh btw @warrengm you've got to update https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/test/fixtures/lantern-master-accuracy.json now too to get the lantern data tests to pass to match the expectations, nice accuracy improvements! :)

@patrickhulce
Copy link
Collaborator

friendly ping on the two last little comments on this, would love to land before 6.0 final :)

@googlebot
Copy link

All (the pull request submitter and all commit authors) CLAs are signed, but one or more commits were authored or co-authored by someone other than the pull request submitter.

We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that by leaving a comment that contains only @googlebot I consent. in this pull request.

Note to project maintainer: There may be cases where the author cannot leave a comment, or the comment is not properly detected as consent. In those cases, you can manually confirm consent of the commit author(s), and set the cla label to yes (if enabled on your project).

ℹ️ Googlers: Go here for more info.

@googlebot googlebot added cla: no and removed cla: yes labels Apr 2, 2020
@patrickhulce
Copy link
Collaborator

@googlebot I consent.

@googlebot
Copy link

CLAs look good, thanks!

ℹ️ Googlers: Go here for more info.

@googlebot googlebot added cla: yes and removed cla: no labels Apr 2, 2020
@patrickhulce patrickhulce merged commit 2b61483 into GoogleChrome:master Apr 2, 2020
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.

4 participants