diff --git a/modules/benchmarks/e2e_test/tree_perf.ts b/modules/benchmarks/e2e_test/tree_perf.ts index 845b468875..95d9659ed0 100644 --- a/modules/benchmarks/e2e_test/tree_perf.ts +++ b/modules/benchmarks/e2e_test/tree_perf.ts @@ -8,62 +8,91 @@ import {runBenchmark, verifyNoBrowserErrors} from 'e2e_util/perf_util'; +interface Worker { + id: string; + prepare?(): void; + work(): void; +} + +const CreateOnlyWorker: Worker = { + id: 'createOnly', + prepare: () => $('#destroyDom').click(), + work: () => $('#createDom').click() +}; + +const CreateAndDestroyWorker: Worker = { + id: 'createDestroy', + work: () => { + $('#createDom').click(); + $('#destroyDom').click(); + } +}; + +const UpdateWorker: Worker = { + id: 'update', + work: () => $('#createDom').click() +}; + describe('tree benchmark perf', () => { afterEach(verifyNoBrowserErrors); - it('should run for ng2', (done) => { - runTreeBenchmark({ - id: 'deepTree.ng2', - url: 'all/benchmarks/src/tree/ng2/index.html', - }).then(done, done.fail); - }); + [CreateOnlyWorker, CreateAndDestroyWorker, UpdateWorker].forEach((worker) => { + describe(worker.id, () => { - 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 ng2', (done) => { + runTreeBenchmark({ + id: `deepTree.ng2.${worker.id}`, + url: 'all/benchmarks/src/tree/ng2/index.html', + }).then(done, done.fail); + }); - it('should run for the baseline', (done) => { - runTreeBenchmark({ - id: 'deepTree.baseline', - url: 'all/benchmarks/src/tree/baseline/index.html', - ignoreBrowserSynchronization: true, - }).then(done, done.fail); - }); + it('should run for ng2 static', (done) => { + runTreeBenchmark({ + id: `deepTree.ng2.static.${worker.id}`, + url: 'all/benchmarks/src/tree/ng2_static/index.html', + }).then(done, done.fail); + }); - it('should run for the baseline dom', (done) => { - runTreeBenchmark({ - id: 'deepTree.baselineDom', - url: 'all/benchmarks/src/tree/baseline_dom/index.html', - ignoreBrowserSynchronization: true, - }).then(done, done.fail); - }); + it('should run for ng2 switch', (done) => { + runTreeBenchmark({ + id: `deepTree.ng2_switch.${worker.id}`, + url: 'all/benchmarks/src/tree/ng2_switch/index.html', + }).then(done, done.fail); + }); - it('should run for the incremental dom', (done) => { - runTreeBenchmark({ - id: 'deepTree.incrementalDom', - url: 'all/benchmarks/src/tree/incremental_dom/index.html', - ignoreBrowserSynchronization: true, - }).then(done, done.fail); - }); + it('should run for the baseline', (done) => { + runTreeBenchmark({ + id: `deepTree.baseline.${worker.id}`, + url: 'all/benchmarks/src/tree/baseline/index.html', + ignoreBrowserSynchronization: true, + }).then(done, done.fail); + }); - it('should run for polymer binary tree', (done) => { - runTreeBenchmark({ - id: 'deepTree.polymer', - url: 'all/benchmarks/src/tree/polymer/index.html', - ignoreBrowserSynchronization: true, - }).then(done, done.fail); - }); + it('should run for incremental-dom', (done) => { + runTreeBenchmark({ + id: `deepTree.incremental_dom.${worker.id}`, + url: 'all/benchmarks/src/tree/incremental_dom/index.html', + ignoreBrowserSynchronization: true, + }).then(done, done.fail); + }); - it('should run for polymer leaves', (done) => { - runTreeBenchmark({ - id: 'deepTree.polymerLeaves', - url: 'all/benchmarks/src/tree/polymer_leaves/index.html', - ignoreBrowserSynchronization: true, - }).then(done, done.fail); + it('should run for polymer binary tree', (done) => { + runTreeBenchmark({ + id: `deepTree.polymer.${worker.id}`, + url: 'all/benchmarks/src/tree/polymer/index.html', + ignoreBrowserSynchronization: true, + }).then(done, done.fail); + }); + + it('should run for polymer leaves', (done) => { + runTreeBenchmark({ + id: `deepTree.polymer_leaves.${worker.id}`, + url: 'all/benchmarks/src/tree/polymer_leaves/index.html', + ignoreBrowserSynchronization: true, + }).then(done, done.fail); + }); + }); }); function runTreeBenchmark( diff --git a/modules/benchmarks/e2e_test/tree_spec.ts b/modules/benchmarks/e2e_test/tree_spec.ts index 2eba0d9525..13bb9bac57 100644 --- a/modules/benchmarks/e2e_test/tree_spec.ts +++ b/modules/benchmarks/e2e_test/tree_spec.ts @@ -24,6 +24,12 @@ describe('tree benchmark spec', () => { }); }); + it('should work for ng2 switch', () => { + testTreeBenchmark({ + url: 'all/benchmarks/src/tree/ng2_switch/index.html', + }); + }); + it('should work for the baseline', () => { testTreeBenchmark({ url: 'all/benchmarks/src/tree/baseline/index.html', @@ -31,14 +37,7 @@ describe('tree benchmark spec', () => { }); }); - it('should work for the baseline dom', () => { - testTreeBenchmark({ - url: 'all/benchmarks/src/tree/baseline_dom/index.html', - ignoreBrowserSynchronization: true, - }); - }); - - it('should work for the incremental dom', () => { + it('should work for incremental dom', () => { testTreeBenchmark({ url: 'all/benchmarks/src/tree/incremental_dom/index.html', ignoreBrowserSynchronization: true, @@ -60,9 +59,15 @@ describe('tree benchmark spec', () => { }); function testTreeBenchmark(openConfig: {url: string, ignoreBrowserSynchronization?: boolean}) { - openBrowser(openConfig); + openBrowser({ + url: openConfig.url, + ignoreBrowserSynchronization: openConfig.ignoreBrowserSynchronization, + params: [{name: 'depth', value: 4}], + }); $('#createDom').click(); expect($('#root').getText()).toContain('0'); + $('#createDom').click(); + expect($('#root').getText()).toContain('A'); $('#destroyDom').click(); expect($('#root').getText()).toEqual(''); } diff --git a/modules/benchmarks/src/tree/baseline/index.html b/modules/benchmarks/src/tree/baseline/index.html index 71af2520e0..b531ca02ac 100644 --- a/modules/benchmarks/src/tree/baseline/index.html +++ b/modules/benchmarks/src/tree/baseline/index.html @@ -2,26 +2,26 @@ -

Params

-
- Depth: - -
- -
+

Params

+
+ Depth: + +
+ +
-

Baseline tree benchmark

-

- - - - -

+

Baseline Tree Benchmark

+

+ + + + +

-
- -
+
+ +
- + \ No newline at end of file diff --git a/modules/benchmarks/src/tree/baseline/index.ts b/modules/benchmarks/src/tree/baseline/index.ts index 9e90915ee7..58a3927cf1 100644 --- a/modules/benchmarks/src/tree/baseline/index.ts +++ b/modules/benchmarks/src/tree/baseline/index.ts @@ -1,19 +1,18 @@ import {bindAction, profile} from '../../util'; import {TreeNode, buildTree, emptyTree} from '../util'; -import {BaseLineTreeComponent} from './tree'; +import {TreeComponent} from './tree'; export function main() { - var app: BaseLineTreeComponent; + var tree: TreeComponent; - function destroyDom() { app.update(emptyTree); } + function destroyDom() { tree.data = emptyTree; } - function createDom() { app.update(buildTree()); } + function createDom() { tree.data = buildTree(); } function noop() {} function init() { - const tree: any = document.querySelector('tree'); - app = new BaseLineTreeComponent(tree); + tree = new TreeComponent(document.querySelector('tree')); bindAction('#destroyDom', destroyDom); bindAction('#createDom', createDom); diff --git a/modules/benchmarks/src/tree/baseline/tree.ts b/modules/benchmarks/src/tree/baseline/tree.ts index 3e500ecd06..98c330ca61 100644 --- a/modules/benchmarks/src/tree/baseline/tree.ts +++ b/modules/benchmarks/src/tree/baseline/tree.ts @@ -1,74 +1,61 @@ -import {__platform_browser_private__} from '@angular/platform-browser'; import {TreeNode} from '../util'; -// 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; +export class TreeComponent { + private _renderNodes: any[]; -const BASELINE_TREE_TEMPLATE = document.createElement('template'); -BASELINE_TREE_TEMPLATE.innerHTML = - '_'; -const BASELINE_IF_TEMPLATE = document.createElement('template'); -BASELINE_IF_TEMPLATE.innerHTML = ''; + constructor(private _rootEl: any) {} -export class BaseLineTreeComponent { - value: BaseLineInterpolation; - left: BaseLineIf; - right: BaseLineIf; - constructor(public element: HTMLElement) { - var clone = getDOM().clone(BASELINE_TREE_TEMPLATE.content.firstChild); - getDOM().appendChild(element, clone); - - var child = clone.firstChild; - this.value = new BaseLineInterpolation(child); - child = getDOM().nextSibling(child); - this.left = new BaseLineIf(child); - child = getDOM().nextSibling(child); - this.right = new BaseLineIf(child); - } - update(value: TreeNode) { - this.value.update(value.value); - this.left.update(value.left); - this.right.update(value.right); - } -} - -export class BaseLineInterpolation { - value: string; - constructor(public textNode: Node) { this.value = null; } - update(value: string) { - if (this.value !== value) { - this.value = value; - getDOM().setText(this.textNode, value + ' '); + set data(data: TreeNode) { + if (!data.left) { + this._destroy(); + } else if (this._renderNodes) { + this._update(data, 0); + } else { + this._create(this._rootEl, data, 0); } } -} -export class BaseLineIf { - condition: boolean; - component: BaseLineTreeComponent; - constructor(public anchor: Node) { - this.condition = false; - this.component = null; + private _create(parentNode: any, dataNode: TreeNode, index: number) { + if (!this._renderNodes) { + this._renderNodes = new Array(dataNode.transitiveChildCount); + } + + const span = document.createElement('span'); + if (dataNode.depth % 2 === 0) { + span.style.backgroundColor = 'grey'; + } + parentNode.appendChild(span); + this._renderNodes[index] = span; + this._updateNode(span, dataNode); + + if (dataNode.left) { + const leftTree = document.createElement('tree'); + parentNode.appendChild(leftTree); + this._create(leftTree, dataNode.left, index + 1); + } + if (dataNode.right) { + const rightTree = document.createElement('tree'); + parentNode.appendChild(rightTree); + this._create(rightTree, dataNode.right, index + dataNode.left.transitiveChildCount + 1); + } } - update(value: TreeNode) { - var newCondition = !!value; - if (this.condition !== newCondition) { - this.condition = newCondition; - if (this.component) { - getDOM().remove(this.component.element); - this.component = null; - } - if (this.condition) { - var element = getDOM().firstChild((getDOM().clone(BASELINE_IF_TEMPLATE)).content); - this.anchor.parentNode.insertBefore(element, getDOM().nextSibling(this.anchor)); - this.component = new BaseLineTreeComponent(getDOM().firstChild(element)); - } + + private _updateNode(renderNode: any, dataNode: TreeNode) { + renderNode.textContent = ` ${dataNode.value} `; + } + + private _update(dataNode: TreeNode, index: number) { + this._updateNode(this._renderNodes[index], dataNode); + if (dataNode.left) { + this._update(dataNode.left, index + 1); } - if (this.component) { - this.component.update(value); + if (dataNode.right) { + this._update(dataNode.right, index + dataNode.left.transitiveChildCount + 1); } } + + private _destroy() { + while (this._rootEl.lastChild) this._rootEl.lastChild.remove(); + this._renderNodes = null; + } } diff --git a/modules/benchmarks/src/tree/baseline_dom/index.ts b/modules/benchmarks/src/tree/baseline_dom/index.ts deleted file mode 100644 index 179a29c706..0000000000 --- a/modules/benchmarks/src/tree/baseline_dom/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -import {bindAction, profile} from '../../util'; -import {TreeNode, buildTree, emptyTree} from '../util'; -import {createTreeTemplate, destroyTreeTemplate} from './tree'; - -export function main() { - var app: any; - - function destroyDom() { destroyTreeTemplate(app); } - - function createDom() { createTreeTemplate(app, buildTree()); } - - function noop() {} - - function init() { - app = document.querySelector('tree'); - - 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/baseline_dom/tree.ts b/modules/benchmarks/src/tree/baseline_dom/tree.ts deleted file mode 100644 index 2c6567b2b8..0000000000 --- a/modules/benchmarks/src/tree/baseline_dom/tree.ts +++ /dev/null @@ -1,30 +0,0 @@ -import {TreeNode} from '../util'; - -// template: -// {{data.value}} -export function createTreeTemplate(parentEl: any, data: TreeNode) { - const rootSpan = document.createElement('span'); - parentEl.appendChild(rootSpan); - rootSpan.appendChild(document.createTextNode(` ${data.value} `)); - - if (data.left) { - const leftTreeSpan = document.createElement('span'); - rootSpan.appendChild(leftTreeSpan); - const leftTree = document.createElement('tree'); - leftTreeSpan.appendChild(leftTree); - createTreeTemplate(leftTree, data.left); - } - if (data.right) { - const rightTreeSpan = document.createElement('span'); - rootSpan.appendChild(rightTreeSpan); - const rightTree = document.createElement('tree'); - rightTreeSpan.appendChild(rightTree); - createTreeTemplate(rightTree, data.right); - } -} - -export function destroyTreeTemplate(el: any) { - while (el.firstChild) el.removeChild(el.firstChild); -} diff --git a/modules/benchmarks/src/tree/incremental_dom/index.html b/modules/benchmarks/src/tree/incremental_dom/index.html index 8cd5386fab..99335bd3e4 100644 --- a/modules/benchmarks/src/tree/incremental_dom/index.html +++ b/modules/benchmarks/src/tree/incremental_dom/index.html @@ -10,7 +10,7 @@ -

Baseline tree benchmark

+

Incremental-Dom Tree Benchmark

diff --git a/modules/benchmarks/src/tree/incremental_dom/index.ts b/modules/benchmarks/src/tree/incremental_dom/index.ts index dffb8c8ce2..70ffe285e3 100644 --- a/modules/benchmarks/src/tree/incremental_dom/index.ts +++ b/modules/benchmarks/src/tree/incremental_dom/index.ts @@ -1,19 +1,19 @@ import {bindAction, profile} from '../../util'; import {TreeNode, buildTree, emptyTree} from '../util'; -import {render} from './tree'; +import {TreeComponent} from './tree'; const {patch} = require('incremental-dom'); export function main() { - var app: any; + var tree: TreeComponent; - function destroyDom() { patch(app, () => render(emptyTree)); } + function destroyDom() { tree.data = emptyTree; } - function createDom() { patch(app, () => render(buildTree())); } + function createDom() { tree.data = buildTree(); } function noop() {} function init() { - app = document.querySelector('tree'); + tree = new TreeComponent(document.querySelector('tree')); bindAction('#destroyDom', destroyDom); bindAction('#createDom', createDom); diff --git a/modules/benchmarks/src/tree/incremental_dom/tree.ts b/modules/benchmarks/src/tree/incremental_dom/tree.ts index 808ccfd676..86ca2e3e30 100644 --- a/modules/benchmarks/src/tree/incremental_dom/tree.ts +++ b/modules/benchmarks/src/tree/incremental_dom/tree.ts @@ -1,26 +1,29 @@ import {TreeNode} from '../util'; -const {elementOpen, elementClose, text} = require('incremental-dom'); +const {patch, elementOpen, elementClose, elementOpenStart, elementOpenEnd, text, attr} = + require('incremental-dom'); -// template: -// {{data.value}} -export function render(data: TreeNode) { - elementOpen('span', '', null); - text(` ${data.value} `); - if (data.left) { - elementOpen('span', '', null); - elementOpen('tree', '', null); - render(data.left); - elementClose('tree'); +export class TreeComponent { + constructor(private _rootEl: any) {} + + set data(data: TreeNode) { patch(this._rootEl, () => this._render(data)); } + + private _render(data: TreeNode) { + elementOpenStart('span', '', null); + if (data.depth % 2 === 0) { + attr('style', 'background-color: grey'); + } + elementOpenEnd(); + text(` ${data.value} `); elementClose('span'); + if (data.left) { + elementOpen('tree', '', null); + this._render(data.left); + elementClose('tree'); + } + if (data.right) { + elementOpen('tree', '', null); + this._render(data.right); + elementClose('tree'); + } } - if (data.right) { - elementOpen('span', '', null); - elementOpen('tree', '', null); - render(data.right); - elementClose('tree'); - elementClose('span'); - } - elementClose('span'); } diff --git a/modules/benchmarks/src/tree/ng2/index.html b/modules/benchmarks/src/tree/ng2/index.html index 231eb44f3e..e64dc34021 100644 --- a/modules/benchmarks/src/tree/ng2/index.html +++ b/modules/benchmarks/src/tree/ng2/index.html @@ -2,26 +2,26 @@ -

Params

-
- Depth: - -
- -
+

Params

+
+ Depth: + +
+ +
-

Angular2 tree benchmark

-

- - - - -

+

Ng2 Tree Benchmark

+

+ + + + +

-
- -
+
+ +
- + - \ No newline at end of file + diff --git a/modules/benchmarks/src/tree/ng2/tree.ts b/modules/benchmarks/src/tree/ng2/tree.ts index a5608bba00..5d49d0fa54 100644 --- a/modules/benchmarks/src/tree/ng2/tree.ts +++ b/modules/benchmarks/src/tree/ng2/tree.ts @@ -7,7 +7,7 @@ import {TreeNode, emptyTree} from '../util'; selector: 'tree', inputs: ['data'], template: - ` {{data.value}} ` + ` {{data.value}} ` }) export class TreeComponent { data: TreeNode = emptyTree; diff --git a/modules/benchmarks/src/tree/ng2_static/index.html b/modules/benchmarks/src/tree/ng2_static/index.html index 17031dfe68..3b4659e1d2 100644 --- a/modules/benchmarks/src/tree/ng2_static/index.html +++ b/modules/benchmarks/src/tree/ng2_static/index.html @@ -9,7 +9,7 @@ -

Angular2 tree benchmark

+

Ng2 Static Tree Benchmark

diff --git a/modules/benchmarks/src/tree/ng2_static/tree.ts b/modules/benchmarks/src/tree/ng2_static/tree.ts index 3a319782e9..e9364d7289 100644 --- a/modules/benchmarks/src/tree/ng2_static/tree.ts +++ b/modules/benchmarks/src/tree/ng2_static/tree.ts @@ -5,9 +5,12 @@ 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'>`; + let template = + ` {{data.value}} `; + if (!isLeaf) { + template += + `<${nextTreeEl} [data]='data.right'><${nextTreeEl} [data]='data.left'>`; + } @Component({selector: `tree${level}`, template: template}) class TreeComponent { diff --git a/modules/benchmarks/src/tree/baseline_dom/index.html b/modules/benchmarks/src/tree/ng2_switch/index.html similarity index 90% rename from modules/benchmarks/src/tree/baseline_dom/index.html rename to modules/benchmarks/src/tree/ng2_switch/index.html index 36f16b5788..ed36bfe46f 100644 --- a/modules/benchmarks/src/tree/baseline_dom/index.html +++ b/modules/benchmarks/src/tree/ng2_switch/index.html @@ -10,7 +10,7 @@ -

Baseline tree benchmark

+

Ng2 with NgSwitch Tree Benchmark

@@ -24,4 +24,4 @@ - \ No newline at end of file + diff --git a/modules/benchmarks/src/tree/ng2_switch/index.ts b/modules/benchmarks/src/tree/ng2_switch/index.ts new file mode 100644 index 0000000000..e8bfd286f2 --- /dev/null +++ b/modules/benchmarks/src/tree/ng2_switch/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, TreeComponent} from './tree'; + +export function main() { + var tree: TreeComponent; + 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_switch/tree.ts b/modules/benchmarks/src/tree/ng2_switch/tree.ts new file mode 100644 index 0000000000..eab1a7dc46 --- /dev/null +++ b/modules/benchmarks/src/tree/ng2_switch/tree.ts @@ -0,0 +1,20 @@ +import {Component, Input, NgModule} from '@angular/core'; +import {BrowserModule} from '@angular/platform-browser'; + +import {TreeNode, emptyTree, flattenTree} from '../util'; + +@Component({ + selector: 'tree', + template: ` + {{data.value}} + {{data.value}} + ` +}) +export class TreeComponent { + @Input() + data: TreeNode = emptyTree; +} + +@NgModule({imports: [BrowserModule], bootstrap: [TreeComponent], declarations: [TreeComponent]}) +export class AppModule { +} diff --git a/modules/benchmarks/src/tree/polymer/binary_tree.html b/modules/benchmarks/src/tree/polymer/binary_tree.html index d1fe165bb7..ebab874dfa 100644 --- a/modules/benchmarks/src/tree/polymer/binary_tree.html +++ b/modules/benchmarks/src/tree/polymer/binary_tree.html @@ -1,15 +1,13 @@ + - + + \ No newline at end of file diff --git a/modules/benchmarks/src/tree/polymer/index.ts b/modules/benchmarks/src/tree/polymer/index.ts index ddc9bab9a1..d230f1d60a 100644 --- a/modules/benchmarks/src/tree/polymer/index.ts +++ b/modules/benchmarks/src/tree/polymer/index.ts @@ -1,4 +1,4 @@ -import {bindAction} from '../../util'; +import {bindAction, profile} from '../../util'; import {buildTree, emptyTree} from '../util'; declare var Polymer: any; @@ -11,6 +11,11 @@ export function main() { function createDom() { rootEl.data = buildTree(); } + function noop() {} + bindAction('#destroyDom', destroyDom); bindAction('#createDom', createDom); + + bindAction('#updateDomProfile', profile(createDom, noop, 'update')); + bindAction('#createDomProfile', profile(createDom, destroyDom, 'create')); } diff --git a/modules/benchmarks/src/tree/polymer_leaves/index.html b/modules/benchmarks/src/tree/polymer_leaves/index.html index b206ebf440..fe51d79feb 100644 --- a/modules/benchmarks/src/tree/polymer_leaves/index.html +++ b/modules/benchmarks/src/tree/polymer_leaves/index.html @@ -1,29 +1,34 @@ + + -

Params

-
- Depth: - -
- -
+

Params

+
+ Depth: + +
+ +
-

Polymer leaves benchmark

-

- - -

+

Polymer Leaves Benchmark

+

+ + + + +

-
- -
+
+ +
- + + diff --git a/modules/benchmarks/src/tree/polymer_leaves/index.ts b/modules/benchmarks/src/tree/polymer_leaves/index.ts index 7c2617f9e2..2a145134de 100644 --- a/modules/benchmarks/src/tree/polymer_leaves/index.ts +++ b/modules/benchmarks/src/tree/polymer_leaves/index.ts @@ -1,13 +1,11 @@ import {bindAction} from '../../util'; -import {TreeNode, buildTree, emptyTree} from '../util'; +import {TreeNode, buildTree, emptyTree, flattenTree} from '../util'; declare var Polymer: any; export function main() { const rootEl: any = document.querySelector('binary-tree'); - rootEl.data = emptyTree; - function destroyDom() { while (rootEl.firstChild) rootEl.removeChild(rootEl.firstChild); } @@ -16,7 +14,7 @@ export function main() { const flatTree = flattenTree(buildTree(), []); for (var i = 0; i < flatTree.length; i++) { const el: any = document.createElement('tree-leaf'); - el.value = flatTree[i]; + el.data = flatTree[i]; rootEl.appendChild(el); } } @@ -24,14 +22,3 @@ export function main() { bindAction('#destroyDom', destroyDom); bindAction('#createDom', createDom); } - -function flattenTree(node: TreeNode, target: string[]): string[] { - target.push(node.value); - if (node.left) { - flattenTree(node.left, target); - } - if (node.right) { - flattenTree(node.right, target); - } - return target; -} diff --git a/modules/benchmarks/src/tree/polymer_leaves/tree_leaf.html b/modules/benchmarks/src/tree/polymer_leaves/tree_leaf.html index f08ed3632e..28f3fce8ff 100644 --- a/modules/benchmarks/src/tree/polymer_leaves/tree_leaf.html +++ b/modules/benchmarks/src/tree/polymer_leaves/tree_leaf.html @@ -1,13 +1,13 @@ diff --git a/modules/benchmarks/src/tree/util.ts b/modules/benchmarks/src/tree/util.ts index 6de028fca1..dce47d329e 100644 --- a/modules/benchmarks/src/tree/util.ts +++ b/modules/benchmarks/src/tree/util.ts @@ -1,36 +1,62 @@ import {getIntParameter} from '../util'; export class TreeNode { - constructor(public value: string, public left: TreeNode, public right: TreeNode) {} + transitiveChildCount: number; + children: TreeNode[]; + + constructor( + public value: string, public depth: number, public maxDepth: number, public left: TreeNode, + public right: TreeNode) { + this.transitiveChildCount = Math.pow(2, (this.maxDepth - this.depth + 1)) - 1; + this.children = this.left ? [this.left, this.right] : []; + } + + // Needed for Polymer as it does not support ternary nor modulo operator + // in expressions + get style(): string { return this.depth % 2 === 0 ? 'background-color: grey' : ''; } } let treeCreateCount: number; export let maxDepth: number; -let numberData: string[]; -let charData: string[]; +let numberData: TreeNode; +let charData: TreeNode; 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)); - } + numberData = _buildTree(0, numberValues); + charData = _buildTree(0, charValues); } -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)); +function _buildTree(currDepth: number, valueFn: (depth: number) => string): TreeNode { + const children = currDepth < maxDepth ? _buildTree(currDepth + 1, valueFn) : null; + return new TreeNode(valueFn(currDepth), currDepth, maxDepth, children, children); } -export const emptyTree = new TreeNode('', null, null); +export const emptyTree = new TreeNode('', 0, 0, null, null); export function buildTree(): TreeNode { treeCreateCount++; - return _buildTree(treeCreateCount % 2 ? numberData : charData); + return treeCreateCount % 2 ? numberData : charData; +} + +function numberValues(depth: number): string { + return depth.toString(); +} + +function charValues(depth: number): string { + return String.fromCharCode('A'.charCodeAt(0) + (depth % 26)); +} + +export function flattenTree(node: TreeNode, target: TreeNode[] = []): TreeNode[] { + target.push(node); + if (node.left) { + flattenTree(node.left, target); + } + if (node.right) { + flattenTree(node.right, target); + } + return target; }