Skip to content

Commit 6dceaf2

Browse files
committed
fix(benchmarks): recreate setup for running benchmarks
1 parent 2ab07d9 commit 6dceaf2

File tree

13 files changed

+251
-91
lines changed

13 files changed

+251
-91
lines changed

build.sh

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ for PACKAGE in \
6969
http \
7070
router \
7171
upgrade \
72-
compiler-cli
72+
compiler-cli \
73+
benchpress
7374
do
7475
PWD=`pwd`
7576
SRCDIR=${PWD}/modules/@angular/${PACKAGE}
@@ -101,7 +102,7 @@ do
101102
find ${DESTDIR} -type f -name '*.d.ts' -print0 | xargs -0 sed -i -E 's/^( +)abstract ([[:alnum:]]+\:)/\1\2/g'
102103
fi
103104

104-
if [[ ${PACKAGE} != compiler-cli ]]; then
105+
if [[ ${PACKAGE} != compiler-cli && ${PACKAGE} != benchpress ]]; then
105106

106107
echo "====== BUNDLING: ${SRCDIR} ====="
107108
mkdir ${DESTDIR}/bundles
@@ -128,6 +129,3 @@ do
128129

129130
fi
130131
done
131-
132-
echo "====== COMPILING: \$(npm bin)/tsc -p benchpress/tsconfig.json ====="
133-
$(npm bin)/tsc -p ./modules/benchpress/tsconfig.json

gulpfile.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const os = require('os');
1212

1313
const srcsToFmt =
1414
['tools/**/*.ts', 'modules/@angular/**/*.ts', '!tools/public_api_guard/**/*.d.ts',
15-
'modules/benchpress/**/*.ts', 'modules/playground/**/*.ts', 'modules/benchmarks/**/*.ts'];
15+
'modules/playground/**/*.ts', 'modules/benchmarks/**/*.ts', 'modules/e2e_util/**/*.ts'];
1616

1717
gulp.task('format:enforce', () => {
1818
const format = require('gulp-clang-format');

modules/@angular/benchpress/tsconfig-es5.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
"sourceMap": true,
88
"baseUrl": ".",
99
"paths": {
10-
"@angular/core": ["../../../dist/packages-dist/core"]
10+
"@angular/core": ["../../../dist/packages-dist/core"],
11+
"selenium-webdriver": ["../../../node_modules/@types/selenium-webdriver/index.d.ts"]
1112
},
1213
"experimentalDecorators": true,
1314
"rootDir": ".",
@@ -20,7 +21,7 @@
2021
"index.ts",
2122
"../../../node_modules/@types/node/index.d.ts",
2223
"../../../node_modules/@types/jasmine/index.d.ts",
23-
"../../node_modules/@types/protractor/index.d.ts",
24-
"../../node_modules/@types/selenium-webdriver/index.d.ts"
24+
"../../../node_modules/@types/protractor/index.d.ts",
25+
"../../../node_modules/zone.js/dist/zone.js.d.ts"
2526
]
2627
}

modules/benchmarks/README.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,24 @@
11
# How to run the benchmarks locally
22

33
## Run in the browser
4-
$ build.sh
4+
$ build.sh (only needed 1x to copy over third party resources)
55
$ cp -r ./modules/benchmarks ./dist/all/
66
$ ./node_modules/.bin/tsc -p modules --emitDecoratorMetadata -w
77
$ gulp serve
88
$ open http://localhost:8000/all/benchmarks/src/tree/ng2/index.html?bundles=false
99

1010
## Run e2e tests
1111
$ export NODE_PATH=$(pwd)/dist/all:$(pwd)/dist/tools
12-
$ ./node_modules/.bin/protractor protractor-js-new-world.conf.js --specs=dist/all/benchmarks/e2e_test/tree_perf.js
12+
$ ./node_modules/.bin/protractor protractor-e2e.conf.js --specs=dist/all/benchmarks/e2e_test/tree_spec.js
13+
14+
Options for protractor with `protractor-e2e.conf.js`:
15+
- `--bundles=true`: use prebuilt bundles
16+
- `--ng-help`: show all available options
17+
18+
## Run benchmarks tests
19+
$ export NODE_PATH=$(pwd)/dist/all:$(pwd)/dist/tools
20+
$ ./node_modules/.bin/protractor protractor-perf.conf.js --specs=dist/all/benchmarks/e2e_test/tree_perf.js
21+
22+
Options for protractor with `protractor-perf.conf.js`:
23+
- `--bundles=true`: use prebuilt bundles
24+
- `--ng-help`: show all available options

modules/benchmarks/e2e_test/tree_perf.ts

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,32 +6,47 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {verifyNoBrowserErrors} from 'e2e_util/e2e_util';
9+
import {runBenchmark, verifyNoBrowserErrors} from 'e2e_util/perf_util';
1010

11-
const useBundles = false;
12-
13-
describe('tree benchmark', function() {
11+
describe('tree benchmark', () => {
1412

1513
afterEach(verifyNoBrowserErrors);
1614

17-
it('should work for the baseline', function() {
18-
browser.ignoreSynchronization = true;
19-
browser.get(`all/benchmarks/src/tree/baseline/index.html?bundles=${useBundles}`);
20-
$('#createDom').click();
21-
expect($('baseline').getText()).toContain('0');
15+
it('should work for the baseline', function(done) {
16+
runBenchmark({
17+
id: 'deepTree.baseline',
18+
url: 'all/benchmarks/src/tree/baseline/index.html',
19+
ignoreBrowserSynchronization: true,
20+
params: [{name: 'depth', value: 9}],
21+
work: () => {
22+
$('#createDom').click();
23+
$('#destroyDom').click();
24+
}
25+
}).then(done, done.fail);
2226
});
2327

24-
it('should work for ng2', function() {
25-
browser.get(`all/benchmarks/src/tree/ng2/index.html?bundles=${useBundles}`);
26-
$('#createDom').click();
27-
expect($('app').getText()).toContain('0');
28+
it('should work for ng2', function(done) {
29+
runBenchmark({
30+
id: 'deepTree.ng2',
31+
url: 'all/benchmarks/src/tree/ng2/index.html',
32+
params: [{name: 'depth', value: 9}],
33+
work: () => {
34+
$('#createDom').click();
35+
$('#destroyDom').click();
36+
}
37+
}).then(done, done.fail)
2838
});
2939

30-
it('should work for polymer', function() {
31-
browser.ignoreSynchronization = true;
32-
browser.get(`all/benchmarks/src/tree/polymer/index.html?bundles=${useBundles}`);
33-
$('#createDom').click();
34-
expect($('#app').getText()).toContain('0');
40+
it('should work for polymer', function(done) {
41+
runBenchmark({
42+
id: 'deepTree.polymer',
43+
url: 'all/benchmarks/src/tree/polymer/index.html',
44+
ignoreBrowserSynchronization: true,
45+
params: [{name: 'depth', value: 9}],
46+
work: () => {
47+
$('#createDom').click();
48+
$('#destroyDom').click();
49+
}
50+
}).then(done, done.fail)
3551
});
36-
3752
});
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/**
2+
* @license
3+
* Copyright Google Inc. All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import {openBrowser, verifyNoBrowserErrors} from 'e2e_util/e2e_util';
10+
11+
const useBundles = false;
12+
13+
describe('tree benchmark', function() {
14+
15+
afterEach(verifyNoBrowserErrors);
16+
17+
it('should work for the baseline', function() {
18+
openBrowser({
19+
url: 'all/benchmarks/src/tree/baseline/index.html',
20+
ignoreBrowserSynchronization: true,
21+
});
22+
$('#createDom').click();
23+
expect($('baseline').getText()).toContain('0');
24+
});
25+
26+
it('should work for ng2', function() {
27+
openBrowser({
28+
url: 'all/benchmarks/src/tree/ng2/index.html',
29+
});
30+
$('#createDom').click();
31+
expect($('app').getText()).toContain('0');
32+
});
33+
34+
it('should work for polymer', function() {
35+
openBrowser({
36+
url: 'all/benchmarks/src/tree/polymer/index.html',
37+
ignoreBrowserSynchronization: true,
38+
});
39+
$('#createDom').click();
40+
expect($('#app').getText()).toContain('0');
41+
});
42+
43+
});

modules/e2e_util/e2e_util.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,43 @@
55
* Use of this source code is governed by an MIT-style license that can be
66
* found in the LICENSE file at https://angular.io/license
77
*/
8-
8+
const yargs = require('yargs');
99
import * as webdriver from 'selenium-webdriver';
1010

11+
let cmdArgs: {'bundles': boolean};
1112

1213
declare var browser: any;
1314
declare var expect: any;
1415

16+
export function readCommandLine(extraOptions?: {[key: string]: any}) {
17+
const options: {[key: string]: any} = {
18+
'bundles': {describe: 'Whether to use the angular bundles or not.', default: false}
19+
};
20+
for (var key in extraOptions) {
21+
options[key] = extraOptions[key];
22+
}
23+
24+
cmdArgs = yargs.usage('Angular e2e test options.').options(options).help('ng-help').wrap(40).argv;
25+
return cmdArgs;
26+
}
27+
28+
export function openBrowser(config: {
29+
url: string,
30+
params?: {name: string, value: any}[],
31+
ignoreBrowserSynchronization?: boolean
32+
}) {
33+
if (config.ignoreBrowserSynchronization) {
34+
browser.ignoreSynchronization = true;
35+
}
36+
var params = config.params || [];
37+
params = params.concat([{name: 'bundles', value: cmdArgs.bundles}]);
38+
39+
var urlParams: string[] = [];
40+
params.forEach((param) => { urlParams.push(param.name + '=' + param.value); });
41+
var url = encodeURI(config.url + '?' + urlParams.join('&'));
42+
browser.get(url);
43+
}
44+
1545
/**
1646
* @experimental This API will be moved to Protractor.
1747
*/

modules/e2e_util/perf_util.ts

Lines changed: 57 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -5,70 +5,73 @@
55
* Use of this source code is governed by an MIT-style license that can be
66
* found in the LICENSE file at https://angular.io/license
77
*/
8-
98
export {verifyNoBrowserErrors} from './e2e_util';
109

11-
var benchpress = (global as any /** TODO #9100 */)['benchpress'];
12-
var bind = benchpress.bind;
13-
var Options = benchpress.Options;
10+
const yargs = require('yargs');
11+
const nodeUuid = require('node-uuid');
12+
import * as fs from 'fs-extra';
1413

15-
export function runClickBenchmark(config: any /** TODO #9100 */) {
16-
browser.ignoreSynchronization = !config.waitForAngular2;
17-
var buttons =
18-
config.buttons.map(function(selector: any /** TODO #9100 */) { return $(selector); });
19-
config.work = function() {
20-
buttons.forEach(function(button: any /** TODO #9100 */) { button.click(); });
21-
};
22-
return runBenchmark(config);
23-
}
14+
import {SeleniumWebDriverAdapter, Options, JsonFileReporter, Validator, RegressionSlopeValidator, ConsoleReporter, SizeValidator, MultiReporter, MultiMetric, Runner, Provider} from '@angular/benchpress';
15+
import {readCommandLine as readE2eCommandLine, openBrowser} from './e2e_util';
16+
17+
let cmdArgs: {'sample-size': number, 'force-gc': boolean, 'dryrun': boolean, 'bundles': boolean};
18+
let runner: Runner;
2419

25-
export function runBenchmark(config: any /** TODO #9100 */) {
26-
return getScaleFactor(browser.params.benchmark.scaling).then(function(scaleFactor) {
27-
var description = {};
28-
var urlParams: any[] /** TODO #9100 */ = [];
29-
if (config.params) {
30-
config.params.forEach(function(param: any /** TODO #9100 */) {
31-
var name = param.name;
32-
var value = applyScaleFactor(param.value, scaleFactor, param.scale);
33-
urlParams.push(name + '=' + value);
34-
(description as any /** TODO #9100 */)[name] = value;
35-
});
36-
}
37-
var url = encodeURI(config.url + '?' + urlParams.join('&'));
38-
return browser.get(url).then(function() {
39-
return (global as any /** TODO #9100 */)['benchpressRunner'].sample({
40-
id: config.id,
41-
execute: config.work,
42-
prepare: config.prepare,
43-
microMetrics: config.microMetrics,
44-
providers: [{provide: Options.SAMPLE_DESCRIPTION, useValue: description}]
45-
});
46-
});
20+
export function readCommandLine() {
21+
cmdArgs = <any>readE2eCommandLine({
22+
'sample-size': {describe: 'Used for perf: sample size.', default: 20},
23+
'force-gc': {describe: 'Used for perf: force gc.', default: false, type: 'boolean'},
24+
'dryrun': {describe: 'If true, only run performance benchmarks once.', default: false},
25+
'bundles': {describe: 'Whether to use the angular bundles or not.', default: false}
4726
});
27+
runner = createBenchpressRunner();
4828
}
4929

50-
function getScaleFactor(possibleScalings: any /** TODO #9100 */) {
51-
return browser.executeScript('return navigator.userAgent').then(function(userAgent: string) {
52-
var scaleFactor = 1;
53-
possibleScalings.forEach(function(entry: any /** TODO #9100 */) {
54-
if (userAgent.match(entry.userAgent)) {
55-
scaleFactor = entry.value;
56-
}
57-
});
58-
return scaleFactor;
30+
export function runBenchmark(config: {
31+
id: string,
32+
url: string,
33+
params: {name: string, value: any}[],
34+
ignoreBrowserSynchronization?: boolean,
35+
microMetrics?: {[key: string]: string},
36+
work?: () => void,
37+
prepare?: () => void,
38+
}): Promise<any> {
39+
openBrowser(config);
40+
41+
var description: {[key: string]: any} = {'bundles': cmdArgs.bundles};
42+
config.params.forEach((param) => { description[param.name] = param.value; });
43+
return runner.sample({
44+
id: config.id,
45+
execute: config.work,
46+
prepare: config.prepare,
47+
microMetrics: config.microMetrics,
48+
providers: [{provide: Options.SAMPLE_DESCRIPTION, useValue: description}]
5949
});
6050
}
6151

62-
function applyScaleFactor(
63-
value: any /** TODO #9100 */, scaleFactor: any /** TODO #9100 */,
64-
method: any /** TODO #9100 */) {
65-
if (method === 'log2') {
66-
return value + Math.log(scaleFactor) / Math.LN2;
67-
} else if (method === 'sqrt') {
68-
return value * Math.sqrt(scaleFactor);
69-
} else if (method === 'linear') {
70-
return value * scaleFactor;
52+
function createBenchpressRunner(): Runner {
53+
let runId = nodeUuid.v1();
54+
if (process.env.GIT_SHA) {
55+
runId = process.env.GIT_SHA + ' ' + runId;
56+
}
57+
const resultsFolder = './dist/benchmark_results';
58+
fs.ensureDirSync(resultsFolder);
59+
let providers: Provider[] = [
60+
SeleniumWebDriverAdapter.PROTRACTOR_PROVIDERS,
61+
{provide: Options.FORCE_GC, useValue: cmdArgs['force-gc']},
62+
{provide: Options.DEFAULT_DESCRIPTION, useValue: {'runId': runId}}, JsonFileReporter.PROVIDERS,
63+
{provide: JsonFileReporter.PATH, useValue: resultsFolder}
64+
];
65+
if (!cmdArgs['dryrun']) {
66+
providers.push({provide: Validator, useExisting: RegressionSlopeValidator});
67+
providers.push(
68+
{provide: RegressionSlopeValidator.SAMPLE_SIZE, useValue: cmdArgs['sample-size']});
69+
providers.push(MultiReporter.provideWith([ConsoleReporter, JsonFileReporter]));
7170
} else {
72-
return value;
71+
providers.push({provide: Validator, useExisting: SizeValidator});
72+
providers.push({provide: SizeValidator.SAMPLE_SIZE, useValue: 1});
73+
providers.push(MultiReporter.provideWith([]));
74+
providers.push(MultiMetric.provideWith([]));
7375
}
76+
return new Runner(providers);
7477
}

protractor-e2e.conf.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
// Make sure that the command line is read as the first thing
2+
// as this could exit node if the help script should be printed.
3+
require('./dist/all/e2e_util/e2e_util').readCommandLine();
4+
15
var BROWSER_OPTIONS = {
26
LocalChrome: {
37
'browserName': 'chrome'
@@ -11,8 +15,6 @@ var BROWSER_OPTIONS = {
1115
}
1216
};
1317

14-
15-
1618
exports.config = {
1719
allScriptsTimeout: 11000,
1820
specs: [

0 commit comments

Comments
 (0)