-
Notifications
You must be signed in to change notification settings - Fork 9.3k
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
Add cpu throttle #747
Add cpu throttle #747
Conversation
is there any way I can check if throttling actually works? |
iterations = 0;
while (iterations < 1000){
somethingExpensive();
iterations++;
} run that in a script tag in the head and our existing perf metrics should capture the cost. |
function disableCPUThrottling(driver) { | ||
return driver.sendCommand('Emulation.setCPUThrottlingRate', NO_CPU_THROTTLE_METRICS); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a thought: I'm curious if it's possible for us to get clever with Lighthouse's usage of CPU throttling. As throttling is relative to the system you're testing on, you can experience some pretty wildly different results. 5x throttling on a high-end Mac is going to be different to 5x throttling on a lower end computer. I wonder if it might be possible to do a pass that could determine system "highendness" and normalize throttling accordingly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, we could use require('os') and check cpu ghz
require('os').cpus()
[ { model: 'Intel(R) Core(TM) i7-5557U CPU @ 3.10GHz',
speed: 3100,
times: { user: 6248100, nice: 0, sys: 5165850, idle: 28768980, irq: 0 } },
{ model: 'Intel(R) Core(TM) i7-5557U CPU @ 3.10GHz',
speed: 3100,
times: { user: 2609450, nice: 0, sys: 1979810, idle: 35592290, irq: 0 } },
{ model: 'Intel(R) Core(TM) i7-5557U CPU @ 3.10GHz',
speed: 3100,
times: { user: 5899370, nice: 0, sys: 4368220, idle: 29913970, irq: 0 } },
{ model: 'Intel(R) Core(TM) i7-5557U CPU @ 3.10GHz',
speed: 3100,
times: { user: 2701570, nice: 0, sys: 2006030, idle: 35473940, irq: 0 } } ]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prolly worth seeing what senor @paulirish thinks of the idea :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ayup, previous discussion over in #33.
We definitely want something browser friendly, so I don't think we should rely on advertised clock speed via the os
module.
IMO calibrating the throttling rate so that all machines achieve an even result is totally worthwhile, but it's something we should start with a design doc and a framework for measurement. IMO the x5 multiplier will tide us over for a while, and we can pick up calibration in a quarter or so.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could use https://developer.chrome.com/extensions/system_cpu in the extension and require('os') in the cli and update it later if we know a better solution
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO the 5X will tide us over for a while, and we can pick up calibration in a quarter or so.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW an early patch for cpu throttling allowed the user to put in their octane results. We would use those to compare against saved results for mobile devices.
@@ -492,7 +492,8 @@ class Driver { | |||
beginEmulation() { | |||
return Promise.all([ | |||
emulation.enableNexus5X(this), | |||
emulation.enableNetworkThrottling(this) | |||
emulation.enableNetworkThrottling(this), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you add the disable flags in this PR too?
#646 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
while you're in there... :)
can you add the --disable-device-emulation
flag as well? So you'll be adding all three: --disable-device-emulation --disable-cpu-throttling --disable-network-throttling
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should I remove --mobile
? or keep it as a shortcut?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes. :)
@@ -492,7 +492,8 @@ class Driver { | |||
beginEmulation() { | |||
return Promise.all([ | |||
emulation.enableNexus5X(this), | |||
emulation.enableNetworkThrottling(this) | |||
emulation.enableNetworkThrottling(this), | |||
//emulation.enableCPUThrottling(this), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CPU throttling should be on by default. Disabled if turned off by the flag.
If users are running LH against real phones, they'll have to do --disable-device-emulation --disable-cpu-throttling --disable-network-throttling
themselves for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Worth this PR including a one-liner comment to the README that mentions that requirement for real phones?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @wardpeet!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
548b01c
to
3083efc
Compare
I have to update the tests so travis will fail but you can already have a look :) |
@@ -61,6 +61,9 @@ const cli = yargs | |||
], 'Configuration:') | |||
.describe({ | |||
'mobile': 'Emulates a Nexus 5X', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's nuke the mobile flag. sorry i wasn't explicit about that but that's what i meant to say in #646
beginEmulation(flags) { | ||
let emulations = []; | ||
|
||
if (!flags.enableDeviceEmulation && flags.mobile) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
enable -> disable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you coming back on these? would love the help. needed these flags yesterday. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes fixing this now :p
@paulirish fixed and updated with tests |
96ac9fa
to
c1a9be3
Compare
disable-device-emulation, disable-cpu-throttling, disable-network-throttling
c1a9be3
to
75e44b7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
review!
@@ -506,7 +517,7 @@ class Driver { | |||
|
|||
/** | |||
* Enable internet connection, using emulated mobile settings if | |||
* `options.flags.mobile` is true. | |||
* `options.flags.disableNetworkThrottling` is false. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mobile
flag is still used below
emulation.enableNetworkThrottling(this) | ||
]); | ||
beginEmulation(flags) { | ||
let emulations = []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reason why I don't use const
here is because I modify the object. When using const I assume the data is not going to be changed. But I can change it :)
// Enable emulation if required. | ||
return Promise.resolve(options.flags.mobile && driver.beginEmulation()) | ||
// Enable emulation | ||
// Will check what emulation needs to be done based on flags |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
one line comment, maybe // Enable emulation based on flags
?
return Promise.resolve(options.flags.mobile && driver.beginEmulation()) | ||
// Enable emulation | ||
// Will check what emulation needs to be done based on flags | ||
return Promise.resolve(driver.beginEmulation(options.flags)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can drop the Promise.resolve
, just return driver.beginEmulation(options.flags)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
correct :) returns a promise anyway
--list-trace-categories Prints a list of all required trace categories and exits [boolean] | ||
--config-path The path to the config JSON. | ||
--perf Use a performance-test-only configuration [boolean] | ||
--mobile Emulates a Nexus 5X [default: true] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
--mobile
still here. This needs to be regenerated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wardpeet can you file an followup issue for our calibration-based throttling?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@paulirish see #820
``` | ||
|
||
## Lighthouse w/ mobile devices | ||
|
||
Lighthouse can run against a real mobile device. You can follow the [Remote Debugging on Android (Legacy Workflow)](https://developer.chrome.com/devtools/docs/remote-debugging-legacy) up through step 3.3, but the TL;DR is install & run adb, enable USB debugging, then port forward 9222 from the device to the machine with Lighthouse. | ||
|
||
Run the cli with --disable-device-emulation=true configuration to disable device emulation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't need the =true
here. Run the cli with --disable-device-emulation flag to disable device emulation.
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we're done here once things from brendan and I are addressed. Excited about this!
emulations.push(emulation.enableNetworkThrottling(this)); | ||
} | ||
|
||
if (!flags.disableCpuThrottling) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's make the cpu throttle disabled by default to start. Once the other stuff like #784 is all done we can flip that flag.
--list-trace-categories Prints a list of all required trace categories and exits [boolean] | ||
--config-path The path to the config JSON. | ||
--perf Use a performance-test-only configuration [boolean] | ||
--mobile Emulates a Nexus 5X [default: true] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wardpeet can you file an followup issue for our calibration-based throttling?
@@ -47,6 +47,31 @@ class TestGathererNoArtifact { | |||
|
|||
const fakeDriver = require('./fake-driver'); | |||
|
|||
function getMockedEmulationDriver(deviceEmulation, networkThrottle, cpuThrottle) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rename to emulationFn
, netThrottleFn
, cpuThrottleFn
}; | ||
let createEmulationCheck = variable => () => { | ||
tests[variable] = true; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nuke empty line on this and the others
sendCommand(command) { | ||
switch (command) { | ||
case 'Network.emulateNetworkConditions': | ||
return Promise.resolve(networkThrottle && networkThrottle()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just wondering if we could do these a tad dryer..
case 'Network.emulateNetworkConditions':
fn = netThrottleFn;
// ...
}
return Promise.resolve(fn && fn());
wdyt?
will have some time today to address these issue, we had some storage crisis. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup this works for me. Thanks so much for making this happen!
will wait for @brendankenny brendan to +1 before landing..
@wardpeet can you resolve the conflicts in preparation to land? |
Yes will merge |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looking good. I'll take a last look once the merge conflicts are resolved
@@ -100,7 +104,7 @@ Example: --output-path=./lighthouse-results.html` | |||
.choices('output', Object.keys(Printer.OUTPUT_MODE)) | |||
|
|||
// default values | |||
.default('mobile', true) | |||
.default('disable-cpu-throttling', true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this default should be in driver.beginEmulation()
as well, since without it there, anyone using LH as a module will be cpu throttled
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added to gather-runner
``` | ||
|
||
## Lighthouse w/ mobile devices | ||
|
||
Lighthouse can run against a real mobile device. You can follow the [Remote Debugging on Android (Legacy Workflow)](https://developer.chrome.com/devtools/docs/remote-debugging-legacy) up through step 3.3, but the TL;DR is install & run adb, enable USB debugging, then port forward 9222 from the device to the machine with Lighthouse. | ||
|
||
Run the cli with --disable-device-emulation configuration to disable device emulation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it seems like you'd want to run with all three --disable-*
flags when running on a real device?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not always because you might still need network throttling. And cpu throttling is disabled by default.
Will have to cleanup gather-runner-test in another PR with the connection Class. But for now the tests work again |
We found a Contributor License Agreement for you (the sender of this pull request) and all commit authors, but as best as we can tell these commits were authored by someone else. If that's the case, please add them to this pull request and have them confirm that they're okay with these commits being contributed to Google. If we're mistaken and you did author these commits, just reply here to confirm. |
@paulirish thanks :) |
Keep in mind that CPU throttling now available but disabled by default until proper UI is added. (GoogleChrome#568, GoogleChrome#784) If you want to use it: `--disable-cpu-throttling=false`
No description provided.