Skip to content
This repository has been archived by the owner on Sep 7, 2022. It is now read-only.

Commit

Permalink
Merge pull request #4 from PolymerLabs/node-perf-tester
Browse files Browse the repository at this point in the history
Node perf tester
  • Loading branch information
Steve Orvell authored Oct 4, 2017
2 parents 05908d5 + c76a520 commit e2baa5c
Show file tree
Hide file tree
Showing 8 changed files with 346 additions and 67 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* text=auto
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
bower_components
node_modules
22 changes: 21 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,24 @@ An element to help performance test other elements.

The perf-tester element accepts an array of `tests` which are html files containing perf tests to run. A simple "runner.html" as is shown in `/demo` can be created to display output.

Each test file should load `perf.js` and call `console.perf()` to start the test and `console.perfEnd()` to finish it.
Each test file should load `perf.js` and call `console.perf()` to start the test and `console.perfEnd()` to finish it.

### Node script

Run the node-script with

node node-perf-tester.js

The available options are:

--runs Number of runs to measure on
--targets The file location of a JSON-structured file with the following format:

[
["<type>", "<url>"]
]

where type is the name of the type you are testing and the url the location of the target under test

--port The port number to connect the protocol to. Use this when you are connecting to a separate device. If this argument is not provided, chrome-headless is used.
--throttling one of [FAST_3G, SLOW_3G] If not running in Chrome headless, you can enable throttling with one of the two options.
98 changes: 98 additions & 0 deletions node-perf-tester.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
const path = require('path');

const CDP = require('chrome-remote-interface');

const argv = require('minimist')(process.argv.slice(2));

const NUMBER_OF_RUNS = argv.runs || 100;

(async function() {
let port = argv.port;
let chrome;

if (!argv.port) {
const chromeLauncher = require('chrome-launcher');
chrome = await chromeLauncher.launch({
chromeFlags:
['--headless', '--disable-gpu', '--remote-debugging-address=0.0.0.0'],
port: 0
});
port = chrome.port;
}

const tab = await CDP.New({port});
const client = await CDP({tab, port});

const {Page, Network, Runtime} = client;

const ONE_MB = 1024 * 1024 / 8;
const throttling = {
FAST_3G: {
downloadThroughput: 1.6 * ONE_MB * .9,
uploadThroughput: .75 * ONE_MB * .9
},
SLOW_3G: {
downloadThroughput: .5 * ONE_MB * .8,
uploadThroughput: .5 * ONE_MB * .8
}
};

await Promise.all([
Page.enable(),
Network.enable(),
port && argv.throttling &&
Network.emulateNetworkConditions(Object.assign(
{}, throttling[argv.throttling], {offline: false, latency: 10})),
Network.clearBrowserCache(),
Network.setCacheDisabled({cacheDisabled: true}),
Network.setBypassServiceWorker({bypass: true}),
]);

let loadEventPromise;

Page.loadEventFired(() => {
loadEventPromise();
});

const options = require(path.join(process.cwd(), argv.targets));

const perfTimings = {};
for (const [type] of options) {
perfTimings[type] = [];
}

process.on('exit', async () => {
for (const [type, timings] of Object.entries(perfTimings)) {
const average = timings.reduce((a, b) => a + b) / timings.length;
console.log(
`Average gain for ${type} in ${timings.length} runs is ${average}`);
}

await CDP.Close({port, id: tab.id});
await client.close();
if (!argv.port) {
await chrome.kill();
}
});

for (let i = 0; i < NUMBER_OF_RUNS; i++) {
for (const [type, url] of options) {
requestType = type;

Page.navigate({url});

await new Promise(resolve => {
loadEventPromise = resolve;
});
const {result: {value: perfTiming}} =
await Runtime.evaluate({expression: 'window.perfTiming'});
// const {result: {value: perfTiming}} = await
// Runtime.evaluate({expression: 'window.performance.timing.loadEventEnd-
// window.performance.timing.navigationStart'});
perfTimings[type].push(perfTiming);
}
process.stdout.write(`${i + 1}/${NUMBER_OF_RUNS}\r`);
}

process.exit(0);
})()
1 change: 1 addition & 0 deletions options.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
11 changes: 11 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "perf-tester",
"version": "0.0.1",
"main": "node-perf-tester.js",
"license": "BSD-3-Clause",
"dependencies": {
"chrome-launcher": "^0.4.0",
"chrome-remote-interface": "^0.24.3",
"minimist": "^1.2.0"
}
}
135 changes: 69 additions & 66 deletions perf.js
Original file line number Diff line number Diff line change
@@ -1,66 +1,69 @@
/**
* @license
* Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
* This code may only be used under the BSD style license found at http:polymer.github.io/LICENSE.txt
* The complete set of authors may be found at http:polymer.github.io/AUTHORS.txt
* The complete set of contributors may be found at http:polymer.github.io/CONTRIBUTORS.txt
* Code distributed by Google as part of the polymer project is also
* subject to an additional IP rights grant found at http:polymer.github.io/PATENTS.txt
*/
// x-browser compat.
(function() {
let wcr = false;

addEventListener('WebComponentsReady', function() {
wcr = true;
});

console.perf = function() {
if (window.HTMLImports && !HTMLImports.useNative && !wcr) {
let fn = console._perf.bind(console);
HTMLImports.whenReady(fn);
} else {
console._perf();
}
};

console._perf = function() {
if (window.gc) {
for (let i=0; i<20; i++) {
gc();
}
}
if (console.time) {
console.time('perf');
}
console.perf.time = performance.now();
};

console.perfEnd = function(info) {
if (window.WebComponents) {
if (!wcr) {
addEventListener('WebComponentsReady', function() {
console._perfEnd(info);
});
} else {
console._perfEnd(info);
}
} else {
console._perfEnd(info);
}
};

console._perfEnd = function(info) {
// force layout
document.body.offsetWidth;
let time = performance.now() - console.perf.time;
if (console.time) {
console.timeEnd('perf');
}
document.title = time.toFixed(1) + 'ms: ' + document.title;
if (window.top !== window) {
window.top.postMessage({time: time + 'ms', info: info}, '*');
}
};

})();
/**
* @license
* Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
* This code may only be used under the BSD style license found at
* http:polymer.github.io/LICENSE.txt The complete set of authors may be found
* at http:polymer.github.io/AUTHORS.txt The complete set of contributors may be
* found at http:polymer.github.io/CONTRIBUTORS.txt Code distributed by Google
* as part of the polymer project is also subject to an additional IP rights
* grant found at http:polymer.github.io/PATENTS.txt
*/
// x-browser compat.
(function() {
let wcr = false;

addEventListener('WebComponentsReady', function() {
wcr = true;
});

console.perf = function() {
if (window.HTMLImports && !HTMLImports.useNative && !wcr) {
let fn = console._perf.bind(console);
HTMLImports.whenReady(fn);
} else {
console._perf();
}
};

console._perf = function() {
if (window.gc) {
for (let i = 0; i < 20; i++) {
gc();
}
}
if (console.time) {
console.time('perf');
}
console.perf.time = performance.now();
};

console.perfEnd = function(info) {
if (window.WebComponents) {
if (!wcr) {
addEventListener('WebComponentsReady', function() {
console._perfEnd(info);
});
} else {
console._perfEnd(info);
}
} else {
console._perfEnd(info);
}
};

console._perfEnd = function(info, options = {}) {
if (!options.skipForceLayout) {
// force layout
document.body.offsetWidth;
}
window.perfTiming = performance.now() - console.perf.time;
if (console.time) {
console.timeEnd('perf');
}
document.title = window.perfTiming.toFixed(1) + 'ms: ' + document.title;
if (window.top !== window) {
window.top.postMessage({time: window.perfTiming + 'ms', info}, '*');
}
};

})();
Loading

0 comments on commit e2baa5c

Please sign in to comment.