Skip to content

Commit

Permalink
perf: add js-web-frameworks benchmark
Browse files Browse the repository at this point in the history
  • Loading branch information
pkozlowski-opensource committed Nov 27, 2019
1 parent c291c8e commit f586042
Show file tree
Hide file tree
Showing 7 changed files with 288 additions and 0 deletions.
13 changes: 13 additions & 0 deletions modules/benchmarks/src/js-web-frameworks/BUILD.bazel
@@ -0,0 +1,13 @@
load("//tools:defaults.bzl", "ts_library")

package(default_visibility = ["//visibility:public"])

ts_library(
name = "perf_lib",
testonly = 1,
srcs = ["perf.spec.ts"],
deps = [
"//modules/e2e_util",
"@npm//protractor",
],
)
41 changes: 41 additions & 0 deletions modules/benchmarks/src/js-web-frameworks/ng2/BUILD.bazel
@@ -0,0 +1,41 @@
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",
# TODO: FW-1004 Type checking is currently not complete.
type_check = False,
deps = [
"//modules/benchmarks/src:util_lib",
"//packages/core",
"//packages/platform-browser",
],
)

ng_rollup_bundle(
name = "bundle",
entry_point = ":index_aot.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"],
)
26 changes: 26 additions & 0 deletions modules/benchmarks/src/js-web-frameworks/ng2/index.html
@@ -0,0 +1,26 @@
<!doctype html>
<html>

<head>
<!-- Prevent the browser from requesting any favicon. -->
<link rel="icon" href="data:,">
</head>

<body>

<h2>Ng2 <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>
</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>
16 changes: 16 additions & 0 deletions modules/benchmarks/src/js-web-frameworks/ng2/index_aot.ts
@@ -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);
75 changes: 75 additions & 0 deletions modules/benchmarks/src/js-web-frameworks/ng2/init.ts
@@ -0,0 +1,75 @@
/**
* @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;
}

// TODO(pk): we probably need to support appending rows, but this would be hard(?) to test with
// benchpress
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();
}

const injector = moduleRef.injector;
appRef = injector.get(ApplicationRef);

component = appRef.components[0].instance;

bindAction('#create1KRows', create1K);
bindAction('#create10KRows', create10K);
bindAction('#deleteAll', deleteAll);
}
51 changes: 51 additions & 0 deletions modules/benchmarks/src/js-web-frameworks/ng2/rows.ts
@@ -0,0 +1,51 @@
/**
* @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 {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, $event)">{{item.label}}</a>
</td>
<td class="col-md-1">
<a href="#" (click)="delete(item, $event)">
<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> = [];

itemById(index: number, item: RowData) { return item.id; }
}

@NgModule({
imports: [BrowserModule],
declarations: [JsWebFrameworksComponent],
bootstrap: [JsWebFrameworksComponent],
})
export class JsWebFrameworksModule {
}
66 changes: 66 additions & 0 deletions modules/benchmarks/src/js-web-frameworks/perf.spec.ts
@@ -0,0 +1,66 @@
/**
* @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(); }
};

// 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].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
});
}

0 comments on commit f586042

Please sign in to comment.