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(oopif): collect network requests from iframes #6922

Merged
merged 6 commits into from
Mar 2, 2019
Merged

core(oopif): collect network requests from iframes #6922

merged 6 commits into from
Mar 2, 2019

Conversation

patrickhulce
Copy link
Collaborator

@patrickhulce patrickhulce commented Jan 3, 2019

Summary
Enables us to collect network domain information from iframes. This is likely going to have a significant impact on performance numbers. I'll want to run DZL on it to get a sense of the impact, but we should consider it a "fix" since you could basically stick your whole site into a cross-origin iframe before and get a 100 performance score before.

I think this is all we really want to tackle for now? Future work could enable some cool stuff like the long awaited "fetch inside service worker" and whatnot, but we'd want some fancier target handling helpers first and this seems like a good, high impact start.

Related Issues/PRs
fixes #6337

DZL, do a barrel roll!

Copy link
Member

@brendankenny brendankenny left a comment

Choose a reason for hiding this comment

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

I haven't thought through the oopif case very much. What are the contention concerns here

CPU/process/thread contention is difficult to even formulate what questions we should be asking, but is the argument that iframe network requests will be competing for the same available network resources so should be factored into our byte-efficiency, etc audits?

@brendankenny
Copy link
Member

Also, this might just be your point about DZL, but how does this affect the metrics? Has anyone done any investigation of TTI in a world of iframes? Seems like network quiet could be dramatically different even if the iframe isn't noticeably affecting when the page is "interactive"?

@patrickhulce
Copy link
Collaborator Author

but is the argument that iframe network requests will be competing for the same available network resources so should be factored into our byte-efficiency, etc audits?

This is the only real contention problem I see iframes posing in an OOPIF world. The story is definitely more complicated than that, but at its simplest I think network requests slowing down main content is the biggest problem we can capture.

I think there are a few other concerns we might want to think through. Like

  1. Do we want to recommend opportunities on things that are inside iframes? IMO we do, and just filter like 3p
  2. (You already mentioned this but) Do network requests inside iframes count towards network quiet? IMO they should since that was what was used when the original TTI investigation was done
  3. Do we go any steps further with other audits? i.e. run all our gatherers in all subtargets too

/**
* Routes network events to their handlers, so we can construct networkRecords
* @param {LH.Protocol.RawEventMessage} event
*/
dispatch(event) {
if (!event.method.startsWith('Network.')) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

in case you're curious like me if this was saving us anytime, it looks like it wasn't

just a switch is ~10x faster

https://jsperf.com/switch-vs-startswith

@devtools-bot
Copy link

DZL is done! Go check it out http://lh-dzl-6922.surge.sh

@patrickhulce
Copy link
Collaborator Author

this one too, I wonder if this should've been considered a breaking change 🤔

@patrickhulce
Copy link
Collaborator Author

@paulirish said he wanted to take a look, thought this was already merged 😆

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.

How should oopifs affect our view of the page?

  • Network: yes any requests should be considered so we can evaluate contention, etc.
  • CPU: nope these are a separate thread and we assume a simple model where we dont need to consider cross-process CPU contention.

Right now this is tackling the network side of things so IMO we are good. :)


// We want to receive information about network requests from iframes, so enable the Network domain.
// Network events from subtargets will be stringified and sent back on `Target.receivedMessageFromTarget`.
this.sendCommand('Target.sendMessageToTarget', {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
this.sendCommand('Target.sendMessageToTarget', {
this.sendCommand('Network.enable', undefined, event.sessionId);

This kind of thing could be possible with the flattened protocol... See https://github.com/GoogleChrome/puppeteer/pull/3827/files We'd also add flatten: true on setAutoAttach.

The sessionId is sent not as a param but as a sibling to params. And then it's received as a sibling to object.id when events come back.

I tried this out, but it adds a bunch of complication around our typing for sendCommand. So IMO it's probably not worth dealing with that right now.

Copy link
Collaborator Author

@patrickhulce patrickhulce Mar 1, 2019

Choose a reason for hiding this comment

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

I tried this out, but it adds a bunch of complication around our typing for sendCommand. So IMO it's probably not worth dealing with that right now.

+1, the direction that method started taking me seemed far more complicated given our existing setup than this approach. As long as it's not disappearing from protocol tomorrow, I think this is better for us :)

Copy link
Member

Choose a reason for hiding this comment

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

I tried this out, but it adds a bunch of complication around our typing for sendCommand

maybe we can work on this so we aren't straightjacketed by our type checker

@paulirish
Copy link
Member

This also flips Network.enable on service workers. I am not sure what affect this has.. In devtools service workers get their own network record, so I'm not sure if we'd be double-counting these requests now?

We can look into this or only flip on Network.enable if the new target is an iframe.

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.

just setting status: We need to resolve the network-requests-in-service-workers concern.

Aside from that, this PR lgtm.

@devtools-bot
Copy link

DZL is done! Go check it out http://lh-dzl-6922.surge.sh

1 similar comment
@devtools-bot
Copy link

DZL is done! Go check it out http://lh-dzl-6922.surge.sh

Copy link
Member

@brendankenny brendankenny left a comment

Choose a reason for hiding this comment

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

LGTM

I still think this is going to do some weird things to our audits with network records from all frames but all the other artifacts from just the main frame, but I guess this is one way to find out :)

*/
onReceivedMessageFromTarget(data) {
/** @type {LH.Protocol.RawMessage} */
const protocolMessage = JSON.parse(data.message);
Copy link
Member

Choose a reason for hiding this comment

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

can you add a comment (jsdoc or inline) about where these messages come from and the expected form? (basically, I assume, stringified protocol responses in the message property)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

done

onReceivedMessageFromTarget(data) {
/** @type {LH.Protocol.RawMessage} */
const protocolMessage = JSON.parse(data.message);
if ('id' in protocolMessage) return;
Copy link
Member

Choose a reason for hiding this comment

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

and a comment here that (I'm assuming like in connection.js) if it has an id it's a command response, and we only care about events

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

done

'network-requests': {
details: {
items: {
length: '>10',
Copy link
Member

Choose a reason for hiding this comment

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

maybe add a comment why this is a good bounds

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

done

@@ -47,8 +47,8 @@ class Driver {
*/
this._eventEmitter = /** @type {CrdpEventEmitter} */ (new EventEmitter());
this._connection = connection;
// currently only used by WPT where just Page and Network are needed
this._devtoolsLog = new DevtoolsLog(/^(Page|Network)\./);
// currently used by network-recorder just Page, Network, and Target are needed
Copy link
Member

Choose a reason for hiding this comment

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

do we need this comment anymore? It's devtoolsLog :)

(at most we could say it's used to provide the artifact of the same name)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

heh, fair, I made a note that its purpose is to save network traffic. Seems like we need something to denote why we are filtering this way.

@patrickhulce
Copy link
Collaborator Author

We need to resolve the network-requests-in-service-workers concern.

@paulirish I limited it to just iframes for now and added tests 👍

@devtools-bot
Copy link

DZL is done! Go check it out http://lh-dzl-6922.surge.sh

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.

lg!

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

Successfully merging this pull request may close these issues.

Lighthouse doesn't handle OOPIFs
4 participants