diff --git a/modules/benchmarks/e2e_test/tree_perf.ts b/modules/benchmarks/e2e_test/tree_perf.ts index 0c5c60dc88..61f3e4d97f 100644 --- a/modules/benchmarks/e2e_test/tree_perf.ts +++ b/modules/benchmarks/e2e_test/tree_perf.ts @@ -19,6 +19,13 @@ describe('tree benchmark perf', () => { }).then(done, done.fail); }); + it('should run for ng2 static', (done) => { + runTreeBenchmark({ + id: 'deepTree.ng2.static', + url: 'all/benchmarks/src/tree/ng2_static/index.html', + }).then(done, done.fail); + }); + it('should run for the baseline', (done) => { runTreeBenchmark({ id: 'deepTree.baseline', diff --git a/modules/benchmarks/e2e_test/tree_spec.ts b/modules/benchmarks/e2e_test/tree_spec.ts index e5fcb8eb45..d3fdd36062 100644 --- a/modules/benchmarks/e2e_test/tree_spec.ts +++ b/modules/benchmarks/e2e_test/tree_spec.ts @@ -18,6 +18,12 @@ describe('tree benchmark spec', () => { }); }); + it('should work for ng2 static', () => { + testTreeBenchmark({ + url: 'all/benchmarks/src/tree/ng2_static/index.html', + }); + }); + it('should work for the baseline', () => { testTreeBenchmark({ url: 'all/benchmarks/src/tree/baseline/index.html', diff --git a/modules/benchmarks/src/old/static_tree/tree_benchmark.html b/modules/benchmarks/src/old/static_tree/tree_benchmark.html deleted file mode 100644 index 2c8e2cbaf8..0000000000 --- a/modules/benchmarks/src/old/static_tree/tree_benchmark.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - -

Params

-
-
- Use Viewcache: - - -
- -
- -

Angular2 static tree benchmark (depth 10)

-

- - - - -

- -

Baseline static tree benchmark (depth 10)

-

- - - - -

- -
- -
- -
- -
- -$SCRIPTS$ - - diff --git a/modules/benchmarks/src/old/static_tree/tree_benchmark.ts b/modules/benchmarks/src/old/static_tree/tree_benchmark.ts deleted file mode 100644 index 39768072a1..0000000000 --- a/modules/benchmarks/src/old/static_tree/tree_benchmark.ts +++ /dev/null @@ -1,325 +0,0 @@ -import {NgIf} from '@angular/common'; -import {Component, NgModule} from '@angular/core'; -import {ApplicationRef} from '@angular/core/src/application_ref'; -import {reflector} from '@angular/core/src/reflection/reflection'; -import {ReflectionCapabilities} from '@angular/core/src/reflection/reflection_capabilities'; -import {document, gc, window} from '@angular/facade/src/browser'; -import {BrowserModule} from '@angular/platform-browser'; -import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; -import {BrowserDomAdapter} from '@angular/platform-browser/src/browser/browser_adapter'; -import {DOM} from '@angular/platform-browser/src/dom/dom_adapter'; -import {bindAction, getIntParameter, getStringParameter, windowProfile, windowProfileEnd} from '@angular/testing/src/benchmark_util'; - -function createBindings(): any[] { - return []; -} - -function setupReflector() { - reflector.reflectionCapabilities = new ReflectionCapabilities(); -} - -const MAX_DEPTH = 10; - -export function main() { - BrowserDomAdapter.makeCurrent(); - - setupReflector(); - - var app; - var appRef; - var baselineRootTreeComponent; - var count = 0; - - function profile(create, destroy, name) { - return function() { - windowProfile(name + ' w GC'); - var duration = 0; - var count = 0; - while (count++ < 150) { - 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`); - }; - } - - function noop() {} - - function createData(): TreeNode { - var values = count++ % 2 == 0 ? ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '*'] : - ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', '-']; - return buildTree(MAX_DEPTH, values, 0); - } - - function ng2DestroyDom() { - app.initData = null; - appRef.tick(); - } - - function ng2CreateDom() { - app.initData = createData(); - appRef.tick(); - } - - @NgModule({ - imports: [BrowserModule], - bootstrap: [AppComponentWithStaticTree], - providers: createBindings() - }) - class AppModule { - } - - function initNg2() { - platformBrowserDynamic().bootstrapModule(AppModule).then((ref) => { - var injector = ref.injector; - appRef = injector.get(ApplicationRef); - - app = ref.instance; - bindAction('#ng2DestroyDom', ng2DestroyDom); - bindAction('#ng2CreateDom', ng2CreateDom); - bindAction('#ng2UpdateDomProfile', profile(ng2CreateDom, noop, 'ng2-update')); - bindAction('#ng2CreateDomProfile', profile(ng2CreateDom, ng2DestroyDom, 'ng2-create')); - }); - } - - function baselineDestroyDom() { baselineRootTreeComponent.update(null); } - - function baselineCreateDom() { baselineRootTreeComponent.update(createData()); } - - function initBaseline() { - var tree = DOM.createElement('tree'); - DOM.appendChild(DOM.querySelector(document, 'baseline'), tree); - baselineRootTreeComponent = new BaselineAppComponent(tree, MAX_DEPTH); - - bindAction('#baselineDestroyDom', baselineDestroyDom); - bindAction('#baselineCreateDom', baselineCreateDom); - - bindAction('#baselineUpdateDomProfile', profile(baselineCreateDom, noop, 'baseline-update')); - bindAction( - '#baselineCreateDomProfile', - profile(baselineCreateDom, baselineDestroyDom, 'baseline-create')); - } - - initNg2(); - initBaseline(); -} - -class TreeNode { - value: string; - left: TreeNode; - right: TreeNode; - constructor(value, left, right) { - this.value = value; - this.left = left; - this.right = right; - } -} - -function buildTree(maxDepth, values, curDepth) { - if (maxDepth === curDepth) return new TreeNode('', null, null); - return new TreeNode( - values[curDepth], buildTree(maxDepth, values, curDepth + 1), - buildTree(maxDepth, values, curDepth + 1)); -} - -// http://jsperf.com/nextsibling-vs-childnodes - -class BaselineAppComponent { - tree: BaseLineTreeComponent = null; - constructor(public element, public depth: number) {} - update(value: TreeNode) { - if (value === null) { - this.tree = null; - DOM.clearNodes(this.element); - } else { - if (this.tree === null) { - this.tree = new BaseLineTreeComponent(this.element, this.depth); - } - this.tree.update(value); - } - } -} - -var BASELINE_TREE_TEMPLATE = null; -class BaseLineTreeComponent { - static getTemplate() { - if (BASELINE_TREE_TEMPLATE === null) { - BASELINE_TREE_TEMPLATE = DOM.createTemplate('_'); - } - return BASELINE_TREE_TEMPLATE; - } - - value: BaseLineInterpolation; - left: BaseLineTreeComponent; - right: BaseLineTreeComponent; - terminal: boolean; - - constructor(public element, remainingDepth: number) { - var clone = DOM.firstChild(DOM.importIntoDoc(BaseLineTreeComponent.getTemplate().content)); - DOM.appendChild(this.element, clone); - var child = clone.firstChild; - this.value = new BaseLineInterpolation(child); - this.terminal = remainingDepth === 0; - if (!this.terminal) { - child = DOM.nextSibling(child); - this.left = new BaseLineTreeComponent(child, remainingDepth - 1); - child = DOM.nextSibling(child); - this.right = new BaseLineTreeComponent(child, remainingDepth - 1); - } - } - update(value: TreeNode) { - this.value.update(value.value); - if (!this.terminal) { - this.left.update(value.left); - this.right.update(value.right); - } - } -} - -class BaseLineInterpolation { - value: string; - textNode; - constructor(textNode) { - this.value = null; - this.textNode = textNode; - } - update(value: string) { - if (this.value !== value) { - this.value = value; - DOM.setText(this.textNode, value + ' '); - } - } -} - -class StaticTreeComponentBase { - _value: TreeNode; - constructor() { this.data = null; } - set data(value: TreeNode) { - // TODO: We need an initial value as otherwise the getter for data.value will fail - // --> this should be already caught in change detection! - value = value !== null ? value : new TreeNode('', null, null); - this._value = value; - } - get data() { return this._value; } -} - -@Component( - {selector: 'tree', inputs: ['data'], directives: [], template: '{{data.value}} '}) -class StaticTreeComponent0 extends StaticTreeComponentBase { -} - -@Component({ - selector: 'tree', - inputs: ['data'], - directives: [StaticTreeComponent0], - template: - ` {{data.value}} ` -}) -class StaticTreeComponent1 extends StaticTreeComponentBase { -} - -@Component({ - selector: 'tree', - inputs: ['data'], - directives: [StaticTreeComponent1], - template: - ` {{data.value}} ` -}) -class StaticTreeComponent2 extends StaticTreeComponentBase { - data: TreeNode; -} - -@Component({ - selector: 'tree', - inputs: ['data'], - directives: [StaticTreeComponent2], - template: - ` {{data.value}} ` -}) -class StaticTreeComponent3 extends StaticTreeComponentBase { -} - -@Component({ - selector: 'tree', - inputs: ['data'], - directives: [StaticTreeComponent3], - template: - ` {{data.value}} ` -}) -class StaticTreeComponent4 extends StaticTreeComponentBase { -} - -@Component({ - selector: 'tree', - inputs: ['data'], - directives: [StaticTreeComponent4], - template: - ` {{data.value}} ` -}) -class StaticTreeComponent5 extends StaticTreeComponentBase { -} - -@Component({ - selector: 'tree', - inputs: ['data'], - directives: [StaticTreeComponent5], - template: - ` {{data.value}} ` -}) -class StaticTreeComponent6 extends StaticTreeComponentBase { -} - -@Component({ - selector: 'tree', - inputs: ['data'], - directives: [StaticTreeComponent6], - template: - ` {{data.value}} ` -}) -class StaticTreeComponent7 extends StaticTreeComponentBase { -} - -@Component({ - selector: 'tree', - inputs: ['data'], - directives: [StaticTreeComponent7], - template: - ` {{data.value}} ` -}) -class StaticTreeComponent8 extends StaticTreeComponentBase { -} - -@Component({ - selector: 'tree', - inputs: ['data'], - directives: [StaticTreeComponent8], - template: - ` {{data.value}} ` -}) -class StaticTreeComponent9 extends StaticTreeComponentBase { -} - -@Component({ - selector: 'app', - directives: [StaticTreeComponent9, NgIf], - template: `` -}) -class AppComponentWithStaticTree { - initData: TreeNode; -} diff --git a/modules/benchmarks/src/tree/ng2_static/index.html b/modules/benchmarks/src/tree/ng2_static/index.html new file mode 100644 index 0000000000..17031dfe68 --- /dev/null +++ b/modules/benchmarks/src/tree/ng2_static/index.html @@ -0,0 +1,26 @@ + + + +

Params

+
+ Depth: + +
+ +
+ +

Angular2 tree benchmark

+

+ + + + +

+ +
+ +
+ + + + \ No newline at end of file diff --git a/modules/benchmarks/src/tree/ng2_static/index.ts b/modules/benchmarks/src/tree/ng2_static/index.ts new file mode 100644 index 0000000000..2a21d68710 --- /dev/null +++ b/modules/benchmarks/src/tree/ng2_static/index.ts @@ -0,0 +1,40 @@ +import {ApplicationRef, NgModule, enableProdMode} from '@angular/core'; +import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; + +import {bindAction, profile} from '../../util'; +import {TreeNode, buildTree, emptyTree} from '../util'; + +import {AppModule, RootTreeComponent} from './tree'; + +export function main() { + var tree: RootTreeComponent; + var appRef: ApplicationRef; + + function destroyDom() { + tree.data = emptyTree; + appRef.tick(); + } + + function createDom() { + tree.data = buildTree(); + appRef.tick(); + } + + function noop() {} + + function init() { + enableProdMode(); + platformBrowserDynamic().bootstrapModule(AppModule).then((ref) => { + const injector = ref.injector; + appRef = injector.get(ApplicationRef); + + tree = appRef.components[0].instance; + bindAction('#destroyDom', destroyDom); + bindAction('#createDom', createDom); + bindAction('#updateDomProfile', profile(createDom, noop, 'update')); + bindAction('#createDomProfile', profile(createDom, destroyDom, 'create')); + }); + } + + init(); +} diff --git a/modules/benchmarks/src/tree/ng2_static/tree.ts b/modules/benchmarks/src/tree/ng2_static/tree.ts new file mode 100644 index 0000000000..3a319782e9 --- /dev/null +++ b/modules/benchmarks/src/tree/ng2_static/tree.ts @@ -0,0 +1,40 @@ +import {Component, Input, NgModule} from '@angular/core'; +import {BrowserModule} from '@angular/platform-browser'; + +import {TreeNode, emptyTree, maxDepth} from '../util'; + +function createTreeComponent(level: number, isLeaf: boolean) { + const nextTreeEl = `tree${level+1}`; + const template = isLeaf ? + ` {{data.value}} ` : + ` {{data.value}} <${nextTreeEl} [data]='data.right'><${nextTreeEl} [data]='data.left'>`; + + @Component({selector: `tree${level}`, template: template}) + class TreeComponent { + @Input() + data: TreeNode; + } + + return TreeComponent; +} + +@Component({selector: 'tree', template: ``}) +export class RootTreeComponent { + @Input() + data: TreeNode = emptyTree; +} + +function createModule(): any { + const components: any[] = [RootTreeComponent]; + for (var i = 0; i <= maxDepth; i++) { + components.push(createTreeComponent(i, i === maxDepth)); + } + + @NgModule({imports: [BrowserModule], bootstrap: [RootTreeComponent], declarations: [components]}) + class AppModule { + } + + return AppModule; +} + +export const AppModule = createModule(); diff --git a/modules/benchmarks/src/tree/util.ts b/modules/benchmarks/src/tree/util.ts index 37e135b040..6de028fca1 100644 --- a/modules/benchmarks/src/tree/util.ts +++ b/modules/benchmarks/src/tree/util.ts @@ -5,7 +5,7 @@ export class TreeNode { } let treeCreateCount: number; -let maxDepth: number; +export let maxDepth: number; let numberData: string[]; let charData: string[];