refactor(benchmarks): make setup nicer
- simplify and correct systemjs config - remove deep imports into Ng2 packages to work with bundles - have separate Ng2 and Polymer bootstrap files
This commit is contained in:
parent
f7b5478e9f
commit
6ea5b05e7c
|
@ -7,21 +7,20 @@
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
"@angular/core": ["../../../dist/packages-dist/core"],
|
"@angular/core": ["../../../dist/packages-dist/core"]
|
||||||
"selenium-webdriver": ["../../../node_modules/@types/selenium-webdriver/index.d.ts"]
|
|
||||||
},
|
},
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
"rootDir": ".",
|
"rootDir": ".",
|
||||||
"sourceRoot": ".",
|
"sourceRoot": ".",
|
||||||
"outDir": "../../../dist/packages-dist/benchpress",
|
"outDir": "../../../dist/packages-dist/benchpress",
|
||||||
"declaration": true
|
"declaration": true,
|
||||||
|
"skipLibCheck": true
|
||||||
},
|
},
|
||||||
"exclude": ["integrationtest"],
|
"exclude": ["integrationtest"],
|
||||||
"files": [
|
"files": [
|
||||||
"index.ts",
|
"index.ts",
|
||||||
"../../../node_modules/@types/node/index.d.ts",
|
"../../../node_modules/@types/node/index.d.ts",
|
||||||
"../../../node_modules/@types/jasmine/index.d.ts",
|
"../../../node_modules/@types/jasmine/index.d.ts",
|
||||||
"../../../node_modules/@types/protractor/index.d.ts",
|
|
||||||
"../../../node_modules/zone.js/dist/zone.js.d.ts"
|
"../../../node_modules/zone.js/dist/zone.js.d.ts"
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -1,61 +0,0 @@
|
||||||
/**
|
|
||||||
* @license
|
|
||||||
* Copyright Google Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
|
||||||
* found in the LICENSE file at https://angular.io/license
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
import {document, window} from './facade/browser';
|
|
||||||
import {NumberWrapper, isBlank} from './facade/lang';
|
|
||||||
import {BrowserDomAdapter} from './private_import_platform-browser';
|
|
||||||
|
|
||||||
var DOM = new BrowserDomAdapter();
|
|
||||||
|
|
||||||
export function getIntParameter(name: string) {
|
|
||||||
return NumberWrapper.parseInt(getStringParameter(name), 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getStringParameter(name: string) {
|
|
||||||
var els = DOM.querySelectorAll(document, `input[name="${name}"]`);
|
|
||||||
var value: any /** TODO #9100 */;
|
|
||||||
var el: any /** TODO #9100 */;
|
|
||||||
|
|
||||||
for (var i = 0; i < els.length; i++) {
|
|
||||||
el = els[i];
|
|
||||||
var type = DOM.type(el);
|
|
||||||
if ((type != 'radio' && type != 'checkbox') || DOM.getChecked(el)) {
|
|
||||||
value = DOM.getValue(el);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isBlank(value)) {
|
|
||||||
throw new Error(`Could not find and input field with name ${name}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function bindAction(selector: string, callback: Function) {
|
|
||||||
var el = DOM.querySelector(document, selector);
|
|
||||||
DOM.on(el, 'click', function(_: any /** TODO #9100 */) { callback(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function microBenchmark(
|
|
||||||
name: any /** TODO #9100 */, iterationCount: any /** TODO #9100 */,
|
|
||||||
callback: any /** TODO #9100 */) {
|
|
||||||
var durationName = `${name}/${iterationCount}`;
|
|
||||||
window.console.time(durationName);
|
|
||||||
callback();
|
|
||||||
window.console.timeEnd(durationName);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function windowProfile(name: string): void {
|
|
||||||
(<any>window.console).profile(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function windowProfileEnd(name: string): void {
|
|
||||||
(<any>window.console).profileEnd(name);
|
|
||||||
}
|
|
|
@ -8,58 +8,52 @@
|
||||||
|
|
||||||
import {runBenchmark, verifyNoBrowserErrors} from 'e2e_util/perf_util';
|
import {runBenchmark, verifyNoBrowserErrors} from 'e2e_util/perf_util';
|
||||||
|
|
||||||
describe('tree benchmark', () => {
|
describe('tree benchmark perf', () => {
|
||||||
|
|
||||||
afterEach(verifyNoBrowserErrors);
|
afterEach(verifyNoBrowserErrors);
|
||||||
|
|
||||||
it('should work for the baseline', (done) => {
|
it('should run for ng2', (done) => {
|
||||||
runBenchmark({
|
runTreeBenchmark({
|
||||||
|
id: 'deepTree.ng2',
|
||||||
|
url: 'all/benchmarks/src/tree/ng2/index.html',
|
||||||
|
}).then(done, done.fail);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should run for the baseline', (done) => {
|
||||||
|
runTreeBenchmark({
|
||||||
id: 'deepTree.baseline',
|
id: 'deepTree.baseline',
|
||||||
url: 'all/benchmarks/src/tree/baseline/index.html',
|
url: 'all/benchmarks/src/tree/baseline/index.html',
|
||||||
ignoreBrowserSynchronization: true,
|
ignoreBrowserSynchronization: true,
|
||||||
params: [{name: 'depth', value: 9}],
|
|
||||||
work: () => {
|
|
||||||
$('#createDom').click();
|
|
||||||
$('#destroyDom').click();
|
|
||||||
}
|
|
||||||
}).then(done, done.fail);
|
}).then(done, done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should work for ng2', (done) => {
|
it('should run for polymer binary tree', (done) => {
|
||||||
runBenchmark({
|
runTreeBenchmark({
|
||||||
id: 'deepTree.ng2',
|
|
||||||
url: 'all/benchmarks/src/tree/ng2/index.html',
|
|
||||||
params: [{name: 'depth', value: 9}],
|
|
||||||
work: () => {
|
|
||||||
$('#createDom').click();
|
|
||||||
$('#destroyDom').click();
|
|
||||||
}
|
|
||||||
}).then(done, done.fail);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should work for polymer binary tree', (done) => {
|
|
||||||
runBenchmark({
|
|
||||||
id: 'deepTree.polymer',
|
id: 'deepTree.polymer',
|
||||||
url: 'all/benchmarks/src/tree/polymer/index.html',
|
url: 'all/benchmarks/src/tree/polymer/index.html',
|
||||||
ignoreBrowserSynchronization: true,
|
ignoreBrowserSynchronization: true,
|
||||||
params: [{name: 'depth', value: 9}],
|
|
||||||
work: () => {
|
|
||||||
$('#createDom').click();
|
|
||||||
$('#destroyDom').click();
|
|
||||||
}
|
|
||||||
}).then(done, done.fail);
|
}).then(done, done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should work for polymer leaves', (done) => {
|
it('should run for polymer leaves', (done) => {
|
||||||
runBenchmark({
|
runTreeBenchmark({
|
||||||
id: 'deepTree.polymerLeaves',
|
id: 'deepTree.polymerLeaves',
|
||||||
url: 'all/benchmarks/src/tree/polymer_leaves/index.html',
|
url: 'all/benchmarks/src/tree/polymer_leaves/index.html',
|
||||||
ignoreBrowserSynchronization: true,
|
ignoreBrowserSynchronization: true,
|
||||||
|
}).then(done, done.fail);
|
||||||
|
});
|
||||||
|
|
||||||
|
function runTreeBenchmark(
|
||||||
|
config: {id: string, url: string, ignoreBrowserSynchronization?: boolean}) {
|
||||||
|
return runBenchmark({
|
||||||
|
id: config.id,
|
||||||
|
url: config.url,
|
||||||
|
ignoreBrowserSynchronization: config.ignoreBrowserSynchronization,
|
||||||
params: [{name: 'depth', value: 9}],
|
params: [{name: 'depth', value: 9}],
|
||||||
work: () => {
|
work: () => {
|
||||||
$('#createDom').click();
|
$('#createDom').click();
|
||||||
$('#destroyDom').click();
|
$('#destroyDom').click();
|
||||||
}
|
}
|
||||||
}).then(done, done.fail);
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,45 +8,42 @@
|
||||||
|
|
||||||
import {openBrowser, verifyNoBrowserErrors} from 'e2e_util/e2e_util';
|
import {openBrowser, verifyNoBrowserErrors} from 'e2e_util/e2e_util';
|
||||||
|
|
||||||
const useBundles = false;
|
describe('tree benchmark spec', () => {
|
||||||
|
|
||||||
describe('tree benchmark', () => {
|
|
||||||
|
|
||||||
afterEach(verifyNoBrowserErrors);
|
afterEach(verifyNoBrowserErrors);
|
||||||
|
|
||||||
|
it('should work for ng2', () => {
|
||||||
|
testTreeBenchmark({
|
||||||
|
url: 'all/benchmarks/src/tree/ng2/index.html',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should work for the baseline', () => {
|
it('should work for the baseline', () => {
|
||||||
openBrowser({
|
testTreeBenchmark({
|
||||||
url: 'all/benchmarks/src/tree/baseline/index.html',
|
url: 'all/benchmarks/src/tree/baseline/index.html',
|
||||||
ignoreBrowserSynchronization: true,
|
ignoreBrowserSynchronization: true,
|
||||||
});
|
});
|
||||||
$('#createDom').click();
|
|
||||||
expect($('baseline').getText()).toContain('0');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should work for ng2', () => {
|
|
||||||
openBrowser({
|
|
||||||
url: 'all/benchmarks/src/tree/ng2/index.html',
|
|
||||||
});
|
|
||||||
$('#createDom').click();
|
|
||||||
expect($('app').getText()).toContain('0');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should work for polymer binary tree', () => {
|
it('should work for polymer binary tree', () => {
|
||||||
openBrowser({
|
testTreeBenchmark({
|
||||||
url: 'all/benchmarks/src/tree/polymer/index.html',
|
url: 'all/benchmarks/src/tree/polymer/index.html',
|
||||||
ignoreBrowserSynchronization: true,
|
ignoreBrowserSynchronization: true,
|
||||||
});
|
});
|
||||||
$('#createDom').click();
|
|
||||||
expect($('#app').getText()).toContain('0');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should work for polymer leaves', () => {
|
it('should work for polymer leaves', () => {
|
||||||
openBrowser({
|
testTreeBenchmark({
|
||||||
url: 'all/benchmarks/src/tree/polymer_leaves/index.html',
|
url: 'all/benchmarks/src/tree/polymer_leaves/index.html',
|
||||||
ignoreBrowserSynchronization: true,
|
ignoreBrowserSynchronization: true,
|
||||||
});
|
});
|
||||||
$('#createDom').click();
|
|
||||||
expect($('#app').getText()).toContain('0');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function testTreeBenchmark(openConfig: {url: string, ignoreBrowserSynchronization?: boolean}) {
|
||||||
|
openBrowser(openConfig);
|
||||||
|
$('#createDom').click();
|
||||||
|
expect($('#root').getText()).toContain('0');
|
||||||
|
$('#destroyDom').click();
|
||||||
|
expect($('#root').getText()).toEqual('');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,8 +6,7 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
(function(global: any) {
|
||||||
(function(global: any /** TODO #9100 */) {
|
|
||||||
|
|
||||||
writeScriptTag('/all/benchmarks/vendor/core.js');
|
writeScriptTag('/all/benchmarks/vendor/core.js');
|
||||||
writeScriptTag('/all/benchmarks/vendor/zone.js');
|
writeScriptTag('/all/benchmarks/vendor/zone.js');
|
||||||
|
@ -18,13 +17,12 @@
|
||||||
(<any>global).benchmarksBootstrap = benchmarksBootstrap;
|
(<any>global).benchmarksBootstrap = benchmarksBootstrap;
|
||||||
|
|
||||||
function benchmarksBootstrap() {
|
function benchmarksBootstrap() {
|
||||||
urlParamsToForm();
|
|
||||||
// check query param
|
// check query param
|
||||||
var useBundles = location.search.indexOf('bundles=false') == -1;
|
var useBundles = location.search.indexOf('bundles=false') == -1;
|
||||||
if (useBundles) {
|
if (useBundles) {
|
||||||
System.config({
|
System.config({
|
||||||
|
defaultJSExtensions: true,
|
||||||
map: {
|
map: {
|
||||||
'index': 'index.js',
|
|
||||||
'@angular/core': '/packages-dist/core/bundles/core.umd.js',
|
'@angular/core': '/packages-dist/core/bundles/core.umd.js',
|
||||||
'@angular/common': '/packages-dist/common/bundles/common.umd.js',
|
'@angular/common': '/packages-dist/common/bundles/common.umd.js',
|
||||||
'@angular/forms': '/packages-dist/forms/bundles/forms.umd.js',
|
'@angular/forms': '/packages-dist/forms/bundles/forms.umd.js',
|
||||||
|
@ -40,8 +38,6 @@
|
||||||
'rxjs': '/all/benchmarks/vendor/rxjs'
|
'rxjs': '/all/benchmarks/vendor/rxjs'
|
||||||
},
|
},
|
||||||
packages: {
|
packages: {
|
||||||
'app': {defaultExtension: 'js'},
|
|
||||||
'../app': {defaultExtension: 'js'},
|
|
||||||
'@angular/core/src/facade': {defaultExtension: 'js'},
|
'@angular/core/src/facade': {defaultExtension: 'js'},
|
||||||
'rxjs': {defaultExtension: 'js'}
|
'rxjs': {defaultExtension: 'js'}
|
||||||
}
|
}
|
||||||
|
@ -51,14 +47,9 @@
|
||||||
'Not using the Angular bundles. Don\'t use this configuration for e2e/performance tests!');
|
'Not using the Angular bundles. Don\'t use this configuration for e2e/performance tests!');
|
||||||
|
|
||||||
System.config({
|
System.config({
|
||||||
map: {
|
defaultJSExtensions: true,
|
||||||
'index': 'index.js',
|
map: {'@angular': '/all/@angular', 'rxjs': '/all/benchmarks/vendor/rxjs'},
|
||||||
'@angular': '/all/@angular',
|
|
||||||
'rxjs': '/all/benchmarks/vendor/rxjs'
|
|
||||||
},
|
|
||||||
packages: {
|
packages: {
|
||||||
'app': {defaultExtension: 'js'},
|
|
||||||
'../app': {defaultExtension: 'js'},
|
|
||||||
'@angular/core': {main: 'index.js', defaultExtension: 'js'},
|
'@angular/core': {main: 'index.js', defaultExtension: 'js'},
|
||||||
'@angular/compiler': {main: 'index.js', defaultExtension: 'js'},
|
'@angular/compiler': {main: 'index.js', defaultExtension: 'js'},
|
||||||
'@angular/router': {main: 'index.js', defaultExtension: 'js'},
|
'@angular/router': {main: 'index.js', defaultExtension: 'js'},
|
||||||
|
@ -72,37 +63,11 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// BOOTSTRAP the app!
|
// BOOTSTRAP the app!
|
||||||
System.import('index').then(function(m: any /** TODO #9100 */) {
|
System.import('index').then(function(m: any) { m.main(); }, console.error.bind(console));
|
||||||
m.main();
|
|
||||||
}, console.error.bind(console));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function writeScriptTag(scriptUrl: string, onload?: string) {
|
||||||
function writeScriptTag(scriptUrl: any /** TODO #9100 */, onload?: any /** TODO #9100 */) {
|
|
||||||
document.write(`<script src="${scriptUrl}" onload="${onload}"></script>`);
|
document.write(`<script src="${scriptUrl}" onload="${onload}"></script>`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// helper script that will read out the url parameters
|
|
||||||
// and store them in appropriate form fields on the page
|
|
||||||
function urlParamsToForm() {
|
|
||||||
var regex = /(\w+)=(\w+)/g;
|
|
||||||
var search = decodeURIComponent(location.search);
|
|
||||||
var match: any[];
|
|
||||||
while (match = regex.exec(search)) {
|
|
||||||
var name = match[1];
|
|
||||||
var value = match[2];
|
|
||||||
var els = document.querySelectorAll('input[name="' + name + '"]');
|
|
||||||
var el: any;
|
|
||||||
for (var i = 0; i < els.length; i++) {
|
|
||||||
el = els[i];
|
|
||||||
if (el.type === 'radio' || el.type === 'checkbox') {
|
|
||||||
el.checked = el.value === value;
|
|
||||||
} else {
|
|
||||||
el.value = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}(window));
|
}(window));
|
|
@ -0,0 +1,26 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function(global: any) {
|
||||||
|
|
||||||
|
writeScriptTag('/all/benchmarks/vendor/core.js');
|
||||||
|
writeScriptTag('/all/benchmarks/vendor/system.src.js', 'benchmarksBootstrap()');
|
||||||
|
|
||||||
|
(<any>global).benchmarksBootstrap = benchmarksBootstrap;
|
||||||
|
|
||||||
|
function benchmarksBootstrap() {
|
||||||
|
System.config({defaultJSExtensions: true});
|
||||||
|
|
||||||
|
// BOOTSTRAP the app!
|
||||||
|
System.import('index').then(function(m: any) { m.main(); }, console.error.bind(console));
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeScriptTag(scriptUrl: string, onload?: string) {
|
||||||
|
document.write(`<script src="${scriptUrl}" onload="${onload}"></script>`);
|
||||||
|
}
|
||||||
|
}(window));
|
|
@ -1,37 +0,0 @@
|
||||||
<!doctype html>
|
|
||||||
<html>
|
|
||||||
<body>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<a href="di/di_benchmark.html">DI benchmark</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="compiler/selector_benchmark.html">Selector benchmark</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="compiler/compiler_benchmark.html">Compiler benchmark</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="element_injector/element_injector_benchmark.html">Element injector benchmark</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="tree/tree_benchmark.html">Tree benchmark</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="static_tree/tree_benchmark.html">Static tree benchmark</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="naive_infinite_scroll/index.html">Naive infinite scroll benchmark</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="largetable/largetable_benchmark.html">Largetable benchmark</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="costs/index.html">Benchmarks measuring costs of things</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="page_load/page_load.html">Benchmark measuring time to bootstrap</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,67 +0,0 @@
|
||||||
import {getIntParameter, windowProfile, windowProfileEnd} from '@angular/platform-browser/testing/benchmark_util';
|
|
||||||
|
|
||||||
export class TreeNode {
|
|
||||||
constructor(public value: string, public left: TreeNode, public right: TreeNode) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
let treeCreateCount: number;
|
|
||||||
let maxDepth: number;
|
|
||||||
let numberData: string[];
|
|
||||||
let charData: string[];
|
|
||||||
|
|
||||||
init();
|
|
||||||
|
|
||||||
function init() {
|
|
||||||
maxDepth = getIntParameter('depth');
|
|
||||||
treeCreateCount = 0;
|
|
||||||
numberData = [];
|
|
||||||
charData = [];
|
|
||||||
for (let i = 0; i < maxDepth; i++) {
|
|
||||||
numberData.push(i.toString());
|
|
||||||
charData.push(String.fromCharCode('A'.charCodeAt(0) + i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function _buildTree(values: string[], curDepth: number = 0): TreeNode {
|
|
||||||
if (maxDepth === curDepth) return new TreeNode('', null, null);
|
|
||||||
return new TreeNode(
|
|
||||||
values[curDepth], _buildTree(values, curDepth + 1), _buildTree(values, curDepth + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function emptyTree(): TreeNode {
|
|
||||||
return new TreeNode('', null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function buildTree(): TreeNode {
|
|
||||||
treeCreateCount++;
|
|
||||||
return _buildTree(treeCreateCount % 2 ? numberData : charData);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function profile(create: () => void, destroy: () => void, name: string) {
|
|
||||||
return function() {
|
|
||||||
windowProfile(name + ' w GC');
|
|
||||||
var duration = 0;
|
|
||||||
var count = 0;
|
|
||||||
while (count++ < 150) {
|
|
||||||
(<any>window)['gc']();
|
|
||||||
var start = window.performance.now();
|
|
||||||
create();
|
|
||||||
duration += window.performance.now() - start;
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
windowProfileEnd(name + ' w GC');
|
|
||||||
window.console.log(`Iterations: ${count}; time: ${duration / count} ms / iteration`);
|
|
||||||
|
|
||||||
windowProfile(name + ' w/o GC');
|
|
||||||
duration = 0;
|
|
||||||
count = 0;
|
|
||||||
while (count++ < 150) {
|
|
||||||
var start = window.performance.now();
|
|
||||||
create();
|
|
||||||
duration += window.performance.now() - start;
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
windowProfileEnd(name + ' w/o GC');
|
|
||||||
window.console.log(`Iterations: ${count}; time: ${duration / count} ms / iteration`);
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -19,9 +19,9 @@
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<baseline></baseline>
|
<tree id="root"></tree>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="../../bootstrap.js"></script>
|
<script src="../../bootstrap_ng2.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -1,23 +1,18 @@
|
||||||
import {BrowserDomAdapter} from '@angular/platform-browser/src/browser/browser_adapter';
|
import {bindAction, profile} from '../../util';
|
||||||
import {bindAction} from '@angular/platform-browser/testing/benchmark_util';
|
import {TreeNode, buildTree, emptyTree} from '../util';
|
||||||
|
import {BaseLineTreeComponent} from './tree';
|
||||||
import {TreeNode, buildTree, emptyTree, profile} from '../app/util';
|
|
||||||
|
|
||||||
import {BaseLineTreeComponent} from './app/tree';
|
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
var app: BaseLineTreeComponent;
|
var app: BaseLineTreeComponent;
|
||||||
|
|
||||||
function destroyDom() { app.update(emptyTree()); }
|
function destroyDom() { app.update(emptyTree); }
|
||||||
|
|
||||||
function createDom() { app.update(buildTree()); }
|
function createDom() { app.update(buildTree()); }
|
||||||
|
|
||||||
function noop() {}
|
function noop() {}
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
BrowserDomAdapter.makeCurrent();
|
const tree: any = document.querySelector('tree');
|
||||||
const tree = document.createElement('tree');
|
|
||||||
document.querySelector('baseline').appendChild(tree);
|
|
||||||
app = new BaseLineTreeComponent(tree);
|
app = new BaseLineTreeComponent(tree);
|
||||||
|
|
||||||
bindAction('#destroyDom', destroyDom);
|
bindAction('#destroyDom', destroyDom);
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
|
import {__platform_browser_private__} from '@angular/platform-browser';
|
||||||
import {TreeNode} from '../../app/util';
|
import {TreeNode} from '../util';
|
||||||
|
|
||||||
// http://jsperf.com/nextsibling-vs-childnodes
|
// Note: We are using the DomAdapter also in the Baseline
|
||||||
|
// so that Ng2 can actually reach the baseline. Once Ng2 is able to generate
|
||||||
|
// code that does not use the DomAdapter any more, we should remove this.
|
||||||
|
__platform_browser_private__.initDomAdapter();
|
||||||
|
const getDOM = __platform_browser_private__.getDOM;
|
||||||
|
|
||||||
const BASELINE_TREE_TEMPLATE = document.createElement('template');
|
const BASELINE_TREE_TEMPLATE = document.createElement('template');
|
||||||
BASELINE_TREE_TEMPLATE.innerHTML =
|
BASELINE_TREE_TEMPLATE.innerHTML =
|
|
@ -19,9 +19,9 @@
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<app></app>
|
<tree id="root"></tree>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="../../bootstrap.js"></script>
|
<script src="../../bootstrap_ng2.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -1,23 +1,22 @@
|
||||||
import {NgModule, enableProdMode} from '@angular/core';
|
import {ApplicationRef, NgModule, enableProdMode} from '@angular/core';
|
||||||
import {ApplicationRef} from '@angular/core/src/application_ref';
|
|
||||||
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
|
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
|
||||||
import {bindAction, windowProfile, windowProfileEnd} from '@angular/platform-browser/testing/benchmark_util';
|
|
||||||
|
|
||||||
import {TreeNode, buildTree, emptyTree, profile} from '../app/util';
|
import {bindAction, profile} from '../../util';
|
||||||
|
import {TreeNode, buildTree, emptyTree} from '../util';
|
||||||
|
|
||||||
import {AppComponent, AppModule} from './app/tree';
|
import {AppModule, TreeComponent} from './tree';
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
var app: AppComponent;
|
var tree: TreeComponent;
|
||||||
var appRef: ApplicationRef;
|
var appRef: ApplicationRef;
|
||||||
|
|
||||||
function destroyDom() {
|
function destroyDom() {
|
||||||
app.initData = emptyTree();
|
tree.data = emptyTree;
|
||||||
appRef.tick();
|
appRef.tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
function createDom() {
|
function createDom() {
|
||||||
app.initData = buildTree();
|
tree.data = buildTree();
|
||||||
appRef.tick();
|
appRef.tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +28,7 @@ export function main() {
|
||||||
var injector = ref.injector;
|
var injector = ref.injector;
|
||||||
appRef = injector.get(ApplicationRef);
|
appRef = injector.get(ApplicationRef);
|
||||||
|
|
||||||
app = appRef.components[0].instance;
|
tree = appRef.components[0].instance;
|
||||||
bindAction('#destroyDom', destroyDom);
|
bindAction('#destroyDom', destroyDom);
|
||||||
bindAction('#createDom', createDom);
|
bindAction('#createDom', createDom);
|
||||||
bindAction('#updateDomProfile', profile(createDom, noop, 'ng2-update'));
|
bindAction('#updateDomProfile', profile(createDom, noop, 'ng2-update'));
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import {Component, NgModule} from '@angular/core';
|
import {Component, NgModule} from '@angular/core';
|
||||||
import {BrowserModule} from '@angular/platform-browser';
|
import {BrowserModule} from '@angular/platform-browser';
|
||||||
|
|
||||||
import {TreeNode, emptyTree} from '../../app/util';
|
import {TreeNode, emptyTree} from '../util';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'tree',
|
selector: 'tree',
|
||||||
|
@ -9,20 +9,10 @@ import {TreeNode, emptyTree} from '../../app/util';
|
||||||
template:
|
template:
|
||||||
`<span> {{data.value}} <span template='ngIf data.right != null'><tree [data]='data.right'></tree></span><span template='ngIf data.left != null'><tree [data]='data.left'></tree></span></span>`
|
`<span> {{data.value}} <span template='ngIf data.right != null'><tree [data]='data.right'></tree></span><span template='ngIf data.left != null'><tree [data]='data.left'></tree></span></span>`
|
||||||
})
|
})
|
||||||
class TreeComponent {
|
export class TreeComponent {
|
||||||
data: TreeNode;
|
data: TreeNode = emptyTree;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({selector: 'app', template: `<tree [data]='initData'></tree>`})
|
@NgModule({imports: [BrowserModule], bootstrap: [TreeComponent], declarations: [TreeComponent]})
|
||||||
export class AppComponent {
|
|
||||||
initData: TreeNode;
|
|
||||||
constructor() { this.initData = emptyTree(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [BrowserModule],
|
|
||||||
bootstrap: [AppComponent],
|
|
||||||
declarations: [TreeComponent, AppComponent]
|
|
||||||
})
|
|
||||||
export class AppModule {
|
export class AppModule {
|
||||||
}
|
}
|
|
@ -20,10 +20,10 @@
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<binary-tree id="app"></binary-tree>
|
<binary-tree id="root"></binary-tree>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="../../bootstrap.js"></script>
|
<script src="../../bootstrap_polymer.js"></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
import {bindAction} from '@angular/platform-browser/testing/benchmark_util';
|
import {bindAction} from '../../util';
|
||||||
|
import {buildTree, emptyTree} from '../util';
|
||||||
import {buildTree, emptyTree} from '../app/util';
|
|
||||||
|
|
||||||
declare var Polymer: any;
|
declare var Polymer: any;
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
const rootEl: any = document.querySelector('binary-tree');
|
const rootEl: any = document.querySelector('binary-tree');
|
||||||
rootEl.data = emptyTree();
|
rootEl.data = emptyTree;
|
||||||
|
|
||||||
function destroyDom() { rootEl.data = emptyTree(); }
|
function destroyDom() { rootEl.data = emptyTree; }
|
||||||
|
|
||||||
function createDom() { rootEl.data = buildTree(); }
|
function createDom() { rootEl.data = buildTree(); }
|
||||||
|
|
||||||
|
|
|
@ -13,17 +13,17 @@
|
||||||
<button>Apply</button>
|
<button>Apply</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<h2>Polymer tree benchmark</h2>
|
<h2>Polymer leaves benchmark</h2>
|
||||||
<p>
|
<p>
|
||||||
<button id="destroyDom">destroyDom</button>
|
<button id="destroyDom">destroyDom</button>
|
||||||
<button id="createDom">createDom</button>
|
<button id="createDom">createDom</button>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<binary-tree id="app"></binary-tree>
|
<binary-tree id="root"></binary-tree>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="../../bootstrap.js"></script>
|
<script src="../../bootstrap_polymer.js"></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
import {bindAction} from '@angular/platform-browser/testing/benchmark_util';
|
import {bindAction} from '../../util';
|
||||||
|
import {TreeNode, buildTree, emptyTree} from '../util';
|
||||||
import {TreeNode, buildTree, emptyTree} from '../app/util';
|
|
||||||
|
|
||||||
declare var Polymer: any;
|
declare var Polymer: any;
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
const rootEl: any = document.querySelector('binary-tree');
|
const rootEl: any = document.querySelector('binary-tree');
|
||||||
|
|
||||||
rootEl.data = emptyTree();
|
rootEl.data = emptyTree;
|
||||||
|
|
||||||
function destroyDom() {
|
function destroyDom() {
|
||||||
while (rootEl.firstChild) rootEl.removeChild(rootEl.firstChild);
|
while (rootEl.firstChild) rootEl.removeChild(rootEl.firstChild);
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
import {getIntParameter} from '../util';
|
||||||
|
|
||||||
|
export class TreeNode {
|
||||||
|
constructor(public value: string, public left: TreeNode, public right: TreeNode) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
let treeCreateCount: number;
|
||||||
|
let maxDepth: number;
|
||||||
|
let numberData: string[];
|
||||||
|
let charData: string[];
|
||||||
|
|
||||||
|
init();
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
maxDepth = getIntParameter('depth');
|
||||||
|
treeCreateCount = 0;
|
||||||
|
numberData = [];
|
||||||
|
charData = [];
|
||||||
|
for (let i = 0; i < maxDepth; i++) {
|
||||||
|
numberData.push(i.toString());
|
||||||
|
charData.push(String.fromCharCode('A'.charCodeAt(0) + i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _buildTree(values: string[], curDepth: number = 0): TreeNode {
|
||||||
|
if (maxDepth === curDepth) return new TreeNode('', null, null);
|
||||||
|
return new TreeNode(
|
||||||
|
values[curDepth], _buildTree(values, curDepth + 1), _buildTree(values, curDepth + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
export const emptyTree = new TreeNode('', null, null);
|
||||||
|
|
||||||
|
export function buildTree(): TreeNode {
|
||||||
|
treeCreateCount++;
|
||||||
|
return _buildTree(treeCreateCount % 2 ? numberData : charData);
|
||||||
|
}
|
|
@ -0,0 +1,90 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
urlParamsToForm();
|
||||||
|
|
||||||
|
export function getIntParameter(name: string) {
|
||||||
|
return parseInt(getStringParameter(name), 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getStringParameter(name: string) {
|
||||||
|
var els = document.querySelectorAll(`input[name="${name}"]`);
|
||||||
|
var value: any;
|
||||||
|
var el: any;
|
||||||
|
|
||||||
|
for (var i = 0; i < els.length; i++) {
|
||||||
|
el = els[i];
|
||||||
|
var type = el.type;
|
||||||
|
if ((type != 'radio' && type != 'checkbox') || el.checked) {
|
||||||
|
value = el.value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value == null) {
|
||||||
|
throw new Error(`Could not find and input field with name ${name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function bindAction(selector: string, callback: () => void) {
|
||||||
|
document.querySelector(selector).addEventListener('click', callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function profile(create: () => void, destroy: () => void, name: string) {
|
||||||
|
return function() {
|
||||||
|
window.console.profile(name + ' w GC');
|
||||||
|
var duration = 0;
|
||||||
|
var count = 0;
|
||||||
|
while (count++ < 150) {
|
||||||
|
(<any>window)['gc']();
|
||||||
|
var start = window.performance.now();
|
||||||
|
create();
|
||||||
|
duration += window.performance.now() - start;
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
window.console.profileEnd();
|
||||||
|
window.console.log(`Iterations: ${count}; time: ${duration / count} ms / iteration`);
|
||||||
|
|
||||||
|
window.console.profile(name + ' w/o GC');
|
||||||
|
duration = 0;
|
||||||
|
count = 0;
|
||||||
|
while (count++ < 150) {
|
||||||
|
var start = window.performance.now();
|
||||||
|
create();
|
||||||
|
duration += window.performance.now() - start;
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
window.console.profileEnd();
|
||||||
|
window.console.log(`Iterations: ${count}; time: ${duration / count} ms / iteration`);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper script that will read out the url parameters
|
||||||
|
// and store them in appropriate form fields on the page
|
||||||
|
function urlParamsToForm() {
|
||||||
|
var regex = /(\w+)=(\w+)/g;
|
||||||
|
var search = decodeURIComponent(location.search);
|
||||||
|
var match: any[];
|
||||||
|
while (match = regex.exec(search)) {
|
||||||
|
var name = match[1];
|
||||||
|
var value = match[2];
|
||||||
|
var els = document.querySelectorAll('input[name="' + name + '"]');
|
||||||
|
var el: any;
|
||||||
|
for (var i = 0; i < els.length; i++) {
|
||||||
|
el = els[i];
|
||||||
|
if (el.type === 'radio' || el.type === 'checkbox') {
|
||||||
|
el.checked = el.value === value;
|
||||||
|
} else {
|
||||||
|
el.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -40,6 +40,9 @@ export function openBrowser(config: {
|
||||||
params.forEach((param) => { urlParams.push(param.name + '=' + param.value); });
|
params.forEach((param) => { urlParams.push(param.name + '=' + param.value); });
|
||||||
var url = encodeURI(config.url + '?' + urlParams.join('&'));
|
var url = encodeURI(config.url + '?' + urlParams.join('&'));
|
||||||
browser.get(url);
|
browser.get(url);
|
||||||
|
if (config.ignoreBrowserSynchronization) {
|
||||||
|
browser.sleep(500);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -16,6 +16,11 @@ var BROWSER_OPTIONS = {
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.config = {
|
exports.config = {
|
||||||
|
onPrepare: function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
browser.ignoreSynchronization = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
allScriptsTimeout: 11000,
|
allScriptsTimeout: 11000,
|
||||||
specs: [
|
specs: [
|
||||||
'dist/all/**/e2e_test/**/*_spec.js'
|
'dist/all/**/e2e_test/**/*_spec.js'
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
require('./dist/all/e2e_util/perf_util').readCommandLine();
|
require('./dist/all/e2e_util/perf_util').readCommandLine();
|
||||||
|
|
||||||
var CHROME_OPTIONS = {
|
var CHROME_OPTIONS = {
|
||||||
'args': ['--js-flags=--expose-gc'],
|
'args': ['--js-flags=--expose-gc', '--no-sandbox'],
|
||||||
'perfLoggingPrefs': {
|
'perfLoggingPrefs': {
|
||||||
'traceCategories': 'v8,blink.console,devtools.timeline,disabled-by-default-devtools.timeline'
|
'traceCategories': 'v8,blink.console,devtools.timeline,disabled-by-default-devtools.timeline'
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,6 @@ var BROWSER_CAPS = {
|
||||||
ChromeOnTravis: {
|
ChromeOnTravis: {
|
||||||
browserName: 'chrome',
|
browserName: 'chrome',
|
||||||
chromeOptions: mergeInto(CHROME_OPTIONS, {
|
chromeOptions: mergeInto(CHROME_OPTIONS, {
|
||||||
'args': ['--no-sandbox'],
|
|
||||||
'binary': process.env.CHROME_BIN
|
'binary': process.env.CHROME_BIN
|
||||||
}),
|
}),
|
||||||
loggingPrefs: {
|
loggingPrefs: {
|
||||||
|
@ -32,6 +31,11 @@ var BROWSER_CAPS = {
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.config = {
|
exports.config = {
|
||||||
|
onPrepare: function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
browser.ignoreSynchronization = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
restartBrowserBetweenTests: true,
|
restartBrowserBetweenTests: true,
|
||||||
allScriptsTimeout: 11000,
|
allScriptsTimeout: 11000,
|
||||||
specs: [
|
specs: [
|
||||||
|
|
|
@ -58,7 +58,7 @@ echo 'travis_fold:end:install.browserstack'
|
||||||
# node tools/chromedriverpatch.js
|
# node tools/chromedriverpatch.js
|
||||||
$(npm bin)/webdriver-manager update
|
$(npm bin)/webdriver-manager update
|
||||||
|
|
||||||
# TODO: install bower packages
|
# install bower packages
|
||||||
# bower install
|
$(npm bin)/bower install
|
||||||
|
|
||||||
echo 'travis_fold:end:INSTALL'
|
echo 'travis_fold:end:INSTALL'
|
||||||
|
|
Loading…
Reference in New Issue