parent
ea37e82e69
commit
df6d6e0b1d
|
@ -0,0 +1,13 @@
|
||||||
|
load("//tools:defaults.bzl", "ts_library")
|
||||||
|
|
||||||
|
package(default_visibility = ["//visibility:public"])
|
||||||
|
|
||||||
|
ts_library(
|
||||||
|
name = "perf_lib",
|
||||||
|
testonly = True,
|
||||||
|
srcs = ["perf.spec.ts"],
|
||||||
|
deps = [
|
||||||
|
"//modules/e2e_util",
|
||||||
|
"@npm//protractor",
|
||||||
|
],
|
||||||
|
)
|
|
@ -0,0 +1,39 @@
|
||||||
|
load("//tools:defaults.bzl", "ng_module", "ng_rollup_bundle", "ts_devserver")
|
||||||
|
load("//modules/benchmarks:benchmark_test.bzl", "benchmark_test")
|
||||||
|
|
||||||
|
package(default_visibility = ["//modules/benchmarks:__subpackages__"])
|
||||||
|
|
||||||
|
ng_module(
|
||||||
|
name = "ng2",
|
||||||
|
srcs = glob(["*.ts"]),
|
||||||
|
generate_ve_shims = True,
|
||||||
|
tsconfig = "//modules/benchmarks:tsconfig-build.json",
|
||||||
|
deps = [
|
||||||
|
"//modules/benchmarks/src:util_lib",
|
||||||
|
"//packages/core",
|
||||||
|
"//packages/platform-browser",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
ng_rollup_bundle(
|
||||||
|
name = "bundle",
|
||||||
|
entry_point = ":index.ts",
|
||||||
|
deps = [
|
||||||
|
":ng2",
|
||||||
|
"@npm//rxjs",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
ts_devserver(
|
||||||
|
name = "prodserver",
|
||||||
|
bootstrap = ["//packages/zone.js/dist:zone.js"],
|
||||||
|
port = 4200,
|
||||||
|
static_files = ["index.html"],
|
||||||
|
deps = [":bundle.min_debug.es2015.js"],
|
||||||
|
)
|
||||||
|
|
||||||
|
benchmark_test(
|
||||||
|
name = "perf",
|
||||||
|
server = ":prodserver",
|
||||||
|
deps = ["//modules/benchmarks/src/js-web-frameworks:perf_lib"],
|
||||||
|
)
|
|
@ -0,0 +1,28 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<!-- Prevent the browser from requesting any favicon. -->
|
||||||
|
<link rel="icon" href="data:,">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h2>Angular <a href="https://www.stefankrause.net/wp/?p=504" target="_blank">JS Web Frameworks benchmark</a></h2>
|
||||||
|
<p>
|
||||||
|
<button id="create1KRows">create 1K rows</button>
|
||||||
|
<button id="create10KRows">create 10K rows</button>
|
||||||
|
<button id="deleteAll">delete all rows</button>
|
||||||
|
<button id="update">update every 10th row</button>
|
||||||
|
<button id="swap">swap 2 rows</button>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<js-web-frameworks id="root">Loading...</js-web-frameworks>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!--load location for ts_devserver-->
|
||||||
|
<script src="/app_bundle.js"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
|
@ -0,0 +1,16 @@
|
||||||
|
/**
|
||||||
|
* @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 {enableProdMode} from '@angular/core';
|
||||||
|
import {platformBrowser} from '@angular/platform-browser';
|
||||||
|
|
||||||
|
import {init} from './init';
|
||||||
|
import {JsWebFrameworksModuleNgFactory} from './rows.ngfactory';
|
||||||
|
|
||||||
|
enableProdMode();
|
||||||
|
platformBrowser().bootstrapModuleFactory(JsWebFrameworksModuleNgFactory).then(init);
|
|
@ -0,0 +1,92 @@
|
||||||
|
/**
|
||||||
|
* @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 {ApplicationRef, NgModuleRef} from '@angular/core';
|
||||||
|
|
||||||
|
import {bindAction} from '../../util';
|
||||||
|
|
||||||
|
import {JsWebFrameworksComponent, JsWebFrameworksModule, RowData} from './rows';
|
||||||
|
|
||||||
|
|
||||||
|
function _random(max: number) {
|
||||||
|
return Math.round(Math.random() * 1000) % max;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildData(count: number): Array<RowData> {
|
||||||
|
const data: Array<RowData> = [];
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
|
data.push({
|
||||||
|
id: i,
|
||||||
|
label: ADJECTIVES[_random(ADJECTIVES.length)] + ' ' + COLOURS[_random(COLOURS.length)] + ' ' +
|
||||||
|
NOUNS[_random(NOUNS.length)]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ADJECTIVES = [
|
||||||
|
'pretty', 'large', 'big', 'small', 'tall', 'short', 'long',
|
||||||
|
'handsome', 'plain', 'quaint', 'clean', 'elegant', 'easy', 'angry',
|
||||||
|
'crazy', 'helpful', 'mushy', 'odd', 'unsightly', 'adorable', 'important',
|
||||||
|
'inexpensive', 'cheap', 'expensive', 'fancy'
|
||||||
|
];
|
||||||
|
const COLOURS = [
|
||||||
|
'red', 'yellow', 'blue', 'green', 'pink', 'brown', 'purple', 'brown', 'white', 'black', 'orange'
|
||||||
|
];
|
||||||
|
const NOUNS = [
|
||||||
|
'table', 'chair', 'house', 'bbq', 'desk', 'car', 'pony', 'cookie', 'sandwich', 'burger', 'pizza',
|
||||||
|
'mouse', 'keyboard'
|
||||||
|
];
|
||||||
|
|
||||||
|
export function init(moduleRef: NgModuleRef<JsWebFrameworksModule>) {
|
||||||
|
let component: JsWebFrameworksComponent;
|
||||||
|
let appRef: ApplicationRef;
|
||||||
|
|
||||||
|
function create1K() {
|
||||||
|
component.data = buildData(1 * 1000);
|
||||||
|
appRef.tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
function create10K() {
|
||||||
|
component.data = buildData(10 * 1000);
|
||||||
|
appRef.tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteAll() {
|
||||||
|
component.data = [];
|
||||||
|
appRef.tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
for (let i = 0; i < component.data.length; i += 10) {
|
||||||
|
component.data[i].label += ' !!!';
|
||||||
|
}
|
||||||
|
appRef.tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
function swapRows() {
|
||||||
|
const data = component.data;
|
||||||
|
if (data.length > 998) {
|
||||||
|
const a = data[1];
|
||||||
|
data[1] = data[998];
|
||||||
|
data[998] = a;
|
||||||
|
}
|
||||||
|
appRef.tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
const injector = moduleRef.injector;
|
||||||
|
appRef = injector.get(ApplicationRef);
|
||||||
|
|
||||||
|
component = appRef.components[0].instance;
|
||||||
|
|
||||||
|
bindAction('#create1KRows', create1K);
|
||||||
|
bindAction('#create10KRows', create10K);
|
||||||
|
bindAction('#deleteAll', deleteAll);
|
||||||
|
bindAction('#update', update);
|
||||||
|
bindAction('#swap', swapRows);
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
/**
|
||||||
|
* @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 {ApplicationRef, Component, NgModule} from '@angular/core';
|
||||||
|
import {BrowserModule} from '@angular/platform-browser';
|
||||||
|
|
||||||
|
export interface RowData {
|
||||||
|
id: number;
|
||||||
|
label: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'js-web-frameworks',
|
||||||
|
template: `
|
||||||
|
<table class="table table-hover table-striped test-data">
|
||||||
|
<tbody>
|
||||||
|
<tr [class.danger]="item.id === selected" *ngFor="let item of data; trackBy: itemById">
|
||||||
|
<td class="col-md-1">{{item.id}}</td>
|
||||||
|
<td class="col-md-4">
|
||||||
|
<a href="#" (click)="select(item.id); $event.preventDefault()">{{item.label}}</a>
|
||||||
|
</td>
|
||||||
|
<td class="col-md-1">
|
||||||
|
<a href="#" (click)="delete(item.id); $event.preventDefault()">
|
||||||
|
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td class="col-md-6"></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
`
|
||||||
|
})
|
||||||
|
export class JsWebFrameworksComponent {
|
||||||
|
data: Array<RowData> = [];
|
||||||
|
selected: number|null;
|
||||||
|
|
||||||
|
constructor(private _appRef: ApplicationRef) {}
|
||||||
|
|
||||||
|
itemById(index: number, item: RowData) { return item.id; }
|
||||||
|
|
||||||
|
select(itemId: number) {
|
||||||
|
this.selected = itemId;
|
||||||
|
this._appRef.tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
delete (itemId: number) {
|
||||||
|
const data = this.data;
|
||||||
|
for (let i = 0, l = data.length; i < l; i++) {
|
||||||
|
if (data[i].id === itemId) {
|
||||||
|
data.splice(i, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._appRef.tick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [BrowserModule],
|
||||||
|
declarations: [JsWebFrameworksComponent],
|
||||||
|
bootstrap: [JsWebFrameworksComponent],
|
||||||
|
})
|
||||||
|
export class JsWebFrameworksModule {
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
/**
|
||||||
|
* @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 {$} from 'protractor';
|
||||||
|
import {runBenchmark, verifyNoBrowserErrors} from '../../../e2e_util/perf_util';
|
||||||
|
|
||||||
|
interface Worker {
|
||||||
|
id: string;
|
||||||
|
prepare?(): void;
|
||||||
|
work(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Create1KWorker: Worker = {
|
||||||
|
id: 'create1K',
|
||||||
|
prepare: () => $('#deleteAll').click(),
|
||||||
|
work: () => $('#create1KRows').click()
|
||||||
|
};
|
||||||
|
|
||||||
|
const Delete1KWorker: Worker = {
|
||||||
|
id: 'delete1K',
|
||||||
|
prepare: () => $('#create1KRows').click(),
|
||||||
|
work: () => { $('#deleteAll').click(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
const UpdateWorker: Worker = {
|
||||||
|
id: 'update',
|
||||||
|
prepare: () => $('#create1KRows').click(),
|
||||||
|
work: () => { $('#update').click(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
const SwapWorker: Worker = {
|
||||||
|
id: 'swap',
|
||||||
|
prepare: () => $('#create1KRows').click(),
|
||||||
|
work: () => { $('#swap').click(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
// In order to make sure that we don't change the ids of the benchmarks, we need to
|
||||||
|
// determine the current test package name from the Bazel target. This is necessary
|
||||||
|
// because previous to the Bazel conversion, the benchmark test ids contained the test
|
||||||
|
// name. e.g. "largeTable.ng2_switch.createDestroy". We determine the name of the
|
||||||
|
// Bazel package where this test runs from the current test target. The Bazel target
|
||||||
|
// looks like: "//modules/benchmarks/src/largetable/{pkg_name}:{target_name}".
|
||||||
|
const testPackageName = process.env['BAZEL_TARGET'] !.split(':')[0].split('/').pop();
|
||||||
|
|
||||||
|
describe('js-web-frameworks benchmark perf', () => {
|
||||||
|
|
||||||
|
afterEach(verifyNoBrowserErrors);
|
||||||
|
|
||||||
|
[Create1KWorker, Delete1KWorker, UpdateWorker, SwapWorker].forEach((worker) => {
|
||||||
|
describe(worker.id, () => {
|
||||||
|
it(`should run benchmark for ${testPackageName}`, done => {
|
||||||
|
runTableBenchmark({
|
||||||
|
id: `js-web-frameworks.${testPackageName}.${worker.id}`,
|
||||||
|
url: '/',
|
||||||
|
ignoreBrowserSynchronization: true,
|
||||||
|
worker: worker
|
||||||
|
}).then(done, done.fail);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function runTableBenchmark(
|
||||||
|
config: {id: string, url: string, ignoreBrowserSynchronization?: boolean, worker: Worker}) {
|
||||||
|
return runBenchmark({
|
||||||
|
id: config.id,
|
||||||
|
url: config.url,
|
||||||
|
ignoreBrowserSynchronization: config.ignoreBrowserSynchronization,
|
||||||
|
params: [],
|
||||||
|
prepare: config.worker.prepare,
|
||||||
|
work: config.worker.work
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in New Issue