From e3e7fe210578cb313b1becb0cfbabfffc1436a9c Mon Sep 17 00:00:00 2001 From: Jan Scheffler Date: Mon, 21 Jun 2021 16:32:25 +0200 Subject: [PATCH 1/5] feat: add Page.emulateCPUThrottling --- docs/api.md | 22 ++++++++++++++++++++++ src/common/Page.ts | 10 ++++++++++ test/emulation.spec.ts | 30 ++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+) diff --git a/docs/api.md b/docs/api.md index 2e7e35965f58f..33f6589bf8c51 100644 --- a/docs/api.md +++ b/docs/api.md @@ -138,6 +138,7 @@ * [page.coverage](#pagecoverage) * [page.deleteCookie(...cookies)](#pagedeletecookiecookies) * [page.emulate(options)](#pageemulateoptions) + * [page.emulateCPUThrottling(rate)](#pageemulatecputhrottlingrate) * [page.emulateIdleState(overrides)](#pageemulateidlestateoverrides) * [page.emulateMediaFeatures(features)](#pageemulatemediafeaturesfeatures) * [page.emulateMediaType(type)](#pageemulatemediatypetype) @@ -1535,6 +1536,27 @@ const iPhone = puppeteer.devices['iPhone 6']; List of all available devices is available in the source code: [src/common/DeviceDescriptors.ts](https://github.com/puppeteer/puppeteer/blob/main/src/common/DeviceDescriptors.ts). +#### page.emulateCPUThrottling(rate) + +- `rate` Rate at which the CPU will be throttled (2x, 3x, ...). Passing `null` disables cpu throttling. +- returns: <[Promise]> + +> **NOTE** Real device CPU performance is impacted by many factors that are not trivial to emulate via the Chrome DevTools Protocol / Puppeteer. e.g core count, L1/L2 cache, thermal throttling impacting performance, architecture etc. Simulating CPU performance can be a good guideline, but ideally also verify any numbers you see on a real mobile device. + +```js +const puppeteer = require('puppeteer'); +const slow3G = puppeteer.networkConditions['Slow 3G']; + +(async () => { + const browser = await puppeteer.launch(); + const page = await browser.newPage(); + await page.emulateCPUThrottling(2); + await page.goto('https://www.google.com'); + // other actions... + await browser.close(); +})(); +``` + #### page.emulateIdleState(overrides) - `overrides` If not set, clears emulation diff --git a/src/common/Page.ts b/src/common/Page.ts index eb2e4d4c90b06..6aed3fb363129 100644 --- a/src/common/Page.ts +++ b/src/common/Page.ts @@ -1587,6 +1587,16 @@ export class Page extends EventEmitter { }); } + async emulateCPUThrottling(rate: number | null): Promise { + assert( + rate === null || rate >= 1, + 'Throttling rate should be greater or equal to 1' + ); + await this._client.send('Emulation.setCPUThrottlingRate', { + rate: rate !== null ? rate : 1, + }); + } + /** * @param features - `>` Given an array of media feature * objects, emulates CSS media features on the page. Each media feature object diff --git a/test/emulation.spec.ts b/test/emulation.spec.ts index eb6f1b957ca84..eb38535b88adf 100644 --- a/test/emulation.spec.ts +++ b/test/emulation.spec.ts @@ -408,4 +408,34 @@ describe('Emulation', () => { await page.emulateNetworkConditions(null); }); }); + + describeFailsFirefox('Page.emulateCPUThrottling', function () { + it('should slow down execution', async () => { + const { page } = getTestState(); + + async function measure() { + const start = new Date(); + await page.evaluate(() => { + let i = 0; + while (i < 1000) { + i++; + } + }); + + const end = new Date(); + return +end - +start; + } + + const baseline = await measure(); + await page.emulateCPUThrottling(100); + const throttledTime = await measure(); + await page.emulateCPUThrottling(null); + const timeWithoutThrottle = await measure(); + + // Throttling is not super precise. 20 has been chosen as very loose + // threshold just to make sure that throttling has at least _some_ effect. + expect(throttledTime / baseline).toBeGreaterThan(20); + expect(timeWithoutThrottle / baseline).toBeLessThan(20); + }); + }); }); From 67ee5e18ef93406918f4f59ad988d225820349ae Mon Sep 17 00:00:00 2001 From: Jan Scheffler Date: Tue, 22 Jun 2021 09:37:10 +0200 Subject: [PATCH 2/5] chore: remove measuring due to flakiness --- test/emulation.spec.ts | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/test/emulation.spec.ts b/test/emulation.spec.ts index eb38535b88adf..eed01733722e0 100644 --- a/test/emulation.spec.ts +++ b/test/emulation.spec.ts @@ -413,29 +413,8 @@ describe('Emulation', () => { it('should slow down execution', async () => { const { page } = getTestState(); - async function measure() { - const start = new Date(); - await page.evaluate(() => { - let i = 0; - while (i < 1000) { - i++; - } - }); - - const end = new Date(); - return +end - +start; - } - - const baseline = await measure(); await page.emulateCPUThrottling(100); - const throttledTime = await measure(); await page.emulateCPUThrottling(null); - const timeWithoutThrottle = await measure(); - - // Throttling is not super precise. 20 has been chosen as very loose - // threshold just to make sure that throttling has at least _some_ effect. - expect(throttledTime / baseline).toBeGreaterThan(20); - expect(timeWithoutThrottle / baseline).toBeLessThan(20); }); }); }); From c7649a8416c71dcd9c1e48f5cd70db95cdc04719 Mon Sep 17 00:00:00 2001 From: Jan Scheffler Date: Tue, 22 Jun 2021 09:53:26 +0200 Subject: [PATCH 3/5] chore: update test description --- test/emulation.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/emulation.spec.ts b/test/emulation.spec.ts index eed01733722e0..ded262a77c170 100644 --- a/test/emulation.spec.ts +++ b/test/emulation.spec.ts @@ -410,7 +410,7 @@ describe('Emulation', () => { }); describeFailsFirefox('Page.emulateCPUThrottling', function () { - it('should slow down execution', async () => { + it('should change the CPU throttling rate successfully', async () => { const { page } = getTestState(); await page.emulateCPUThrottling(100); From 9dd1dfde9b92f8ea380f84c6f3b4d09b15ce3cd6 Mon Sep 17 00:00:00 2001 From: Jan Scheffler Date: Tue, 22 Jun 2021 12:15:02 +0200 Subject: [PATCH 4/5] chore: rename rate to factor --- docs/api.md | 2 +- src/common/Page.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/api.md b/docs/api.md index 33f6589bf8c51..7902eb56c4588 100644 --- a/docs/api.md +++ b/docs/api.md @@ -138,7 +138,7 @@ * [page.coverage](#pagecoverage) * [page.deleteCookie(...cookies)](#pagedeletecookiecookies) * [page.emulate(options)](#pageemulateoptions) - * [page.emulateCPUThrottling(rate)](#pageemulatecputhrottlingrate) + * [page.emulateCPUThrottling(factor)](#pageemulatecputhrottlingfactor) * [page.emulateIdleState(overrides)](#pageemulateidlestateoverrides) * [page.emulateMediaFeatures(features)](#pageemulatemediafeaturesfeatures) * [page.emulateMediaType(type)](#pageemulatemediatypetype) diff --git a/src/common/Page.ts b/src/common/Page.ts index 6aed3fb363129..c5b696089fd90 100644 --- a/src/common/Page.ts +++ b/src/common/Page.ts @@ -1587,13 +1587,13 @@ export class Page extends EventEmitter { }); } - async emulateCPUThrottling(rate: number | null): Promise { + async emulateCPUThrottling(factor: number | null): Promise { assert( - rate === null || rate >= 1, + factor === null || factor >= 1, 'Throttling rate should be greater or equal to 1' ); await this._client.send('Emulation.setCPUThrottlingRate', { - rate: rate !== null ? rate : 1, + rate: factor !== null ? factor : 1, }); } From c6680846312e1745ecfabd875465ad7bb43b1b5a Mon Sep 17 00:00:00 2001 From: Jan Scheffler Date: Tue, 22 Jun 2021 13:18:07 +0200 Subject: [PATCH 5/5] chore: update documentation --- docs/api.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api.md b/docs/api.md index 7902eb56c4588..9862a0f704a25 100644 --- a/docs/api.md +++ b/docs/api.md @@ -1536,9 +1536,9 @@ const iPhone = puppeteer.devices['iPhone 6']; List of all available devices is available in the source code: [src/common/DeviceDescriptors.ts](https://github.com/puppeteer/puppeteer/blob/main/src/common/DeviceDescriptors.ts). -#### page.emulateCPUThrottling(rate) +#### page.emulateCPUThrottling(factor) -- `rate` Rate at which the CPU will be throttled (2x, 3x, ...). Passing `null` disables cpu throttling. +- `factor` Factor at which the CPU will be throttled (2x, 2.5x. 3x, ...). Passing `null` disables cpu throttling. - returns: <[Promise]> > **NOTE** Real device CPU performance is impacted by many factors that are not trivial to emulate via the Chrome DevTools Protocol / Puppeteer. e.g core count, L1/L2 cache, thermal throttling impacting performance, architecture etc. Simulating CPU performance can be a good guideline, but ideally also verify any numbers you see on a real mobile device.