diff --git a/modules/benchmarks/e2e_test/largetable_perf.ts b/modules/benchmarks/e2e_test/largetable_perf.ts new file mode 100644 index 0000000000..4de1b9221c --- /dev/null +++ b/modules/benchmarks/e2e_test/largetable_perf.ts @@ -0,0 +1,89 @@ +/** + * @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 {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('largetable benchmark perf', () => { + + afterEach(verifyNoBrowserErrors); + + [CreateOnlyWorker, CreateAndDestroyWorker, UpdateWorker].forEach((worker) => { + describe(worker.id, () => { + it('should run for ng2', (done) => { + runTableBenchmark({ + id: `largeTable.ng2.${worker.id}`, + url: 'all/benchmarks/src/largetable/ng2/index.html', + worker: worker + }).then(done, done.fail); + }); + + it('should run for ng2 with ngSwitch', (done) => { + runTableBenchmark({ + id: `largeTable.ng2_switch.${worker.id}`, + url: 'all/benchmarks/src/largetable/ng2_switch/index.html', + worker: worker + }).then(done, done.fail); + }); + + it('should run for the baseline', (done) => { + runTableBenchmark({ + id: `largeTable.baseline.${worker.id}`, + url: 'all/benchmarks/src/largetable/baseline/index.html', + ignoreBrowserSynchronization: true, + worker: worker + }).then(done, done.fail); + }); + + it('should run for incremental-dom', (done) => { + runTableBenchmark({ + id: `largeTable.incremental_dom.${worker.id}`, + url: 'all/benchmarks/src/largetable/incremental_dom/index.html', + 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: [{name: 'cols', value: 40}, {name: 'rows', value: 200}], + prepare: config.worker.prepare, + work: config.worker.work + }); + } +}); diff --git a/modules/benchmarks/e2e_test/largetable_spec.ts b/modules/benchmarks/e2e_test/largetable_spec.ts new file mode 100644 index 0000000000..091d78115b --- /dev/null +++ b/modules/benchmarks/e2e_test/largetable_spec.ts @@ -0,0 +1,54 @@ +/** + * @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 {openBrowser, verifyNoBrowserErrors} from 'e2e_util/e2e_util'; + +describe('largetable benchmark spec', () => { + + afterEach(verifyNoBrowserErrors); + + it('should work for ng2', () => { + testTreeBenchmark({ + url: 'all/benchmarks/src/largetable/ng2/index.html', + }); + }); + + it('should work for ng2 switch', () => { + testTreeBenchmark({ + url: 'all/benchmarks/src/largetable/ng2_switch/index.html', + }); + }); + + it('should work for the baseline', () => { + testTreeBenchmark({ + url: 'all/benchmarks/src/largetable/baseline/index.html', + ignoreBrowserSynchronization: true, + }); + }); + + it('should work for the incremental-dom', () => { + testTreeBenchmark({ + url: 'all/benchmarks/src/largetable/incremental_dom/index.html', + ignoreBrowserSynchronization: true, + }); + }); + + function testTreeBenchmark(openConfig: {url: string, ignoreBrowserSynchronization?: boolean}) { + openBrowser({ + url: openConfig.url, + ignoreBrowserSynchronization: openConfig.ignoreBrowserSynchronization, + params: [{name: 'cols', value: 5}, {name: 'rows', value: 5}], + }); + $('#createDom').click(); + expect($('#root').getText()).toContain('0/0'); + $('#createDom').click(); + expect($('#root').getText()).toContain('A/A'); + $('#destroyDom').click(); + expect($('#root').getText()).toEqual(''); + } +}); diff --git a/modules/benchmarks/src/largetable/baseline/index.html b/modules/benchmarks/src/largetable/baseline/index.html new file mode 100644 index 0000000000..faf53dbce7 --- /dev/null +++ b/modules/benchmarks/src/largetable/baseline/index.html @@ -0,0 +1,30 @@ + + + + +

Params

+
+ Cols: + +
+ Rows: + +
+ +
+ +

Baseline Largetable Benchmark

+

+ + + + +

+ +
+ +
+ + + + \ No newline at end of file diff --git a/modules/benchmarks/src/largetable/baseline/index.ts b/modules/benchmarks/src/largetable/baseline/index.ts new file mode 100644 index 0000000000..d3458cd310 --- /dev/null +++ b/modules/benchmarks/src/largetable/baseline/index.ts @@ -0,0 +1,25 @@ +import {bindAction, profile} from '../../util'; +import {buildTable, emptyTable} from '../util'; +import {TableComponent} from './table'; + +export function main() { + var table: TableComponent; + + function destroyDom() { table.data = emptyTable; } + + function createDom() { table.data = buildTable(); } + + function noop() {} + + function init() { + table = new TableComponent(document.querySelector('largetable')); + + 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/largetable/baseline/table.ts b/modules/benchmarks/src/largetable/baseline/table.ts new file mode 100644 index 0000000000..2f07694e56 --- /dev/null +++ b/modules/benchmarks/src/largetable/baseline/table.ts @@ -0,0 +1,64 @@ +import {TableCell} from '../util'; + +export class TableComponent { + private _renderCells: any[][]; + constructor(private _rootEl: any) {} + + set data(data: TableCell[][]) { + if (data.length === 0) { + this._destroy(); + } else if (this._renderCells) { + this._update(data); + } else { + this._create(data); + } + } + + private _destroy() { + while (this._rootEl.lastChild) { + this._rootEl.lastChild.remove(); + } + this._renderCells = null; + } + + private _update(data: TableCell[][]) { + for (let r = 0; r < data.length; r++) { + const dataRow = data[r]; + const renderRow = this._renderCells[r]; + for (let c = 0; c < dataRow.length; c++) { + const dataCell = dataRow[c]; + const renderCell = renderRow[c]; + this._updateCell(renderCell, dataCell); + } + } + } + + private _updateCell(renderCell: any, dataCell: TableCell) { + renderCell.textContent = dataCell.value; + } + + private _create(data: TableCell[][]) { + const table = document.createElement('table'); + this._rootEl.appendChild(table); + const tbody = document.createElement('tbody'); + table.appendChild(tbody); + this._renderCells = new Array(data.length); + for (let r = 0; r < data.length; r++) { + const dataRow = data[r]; + const tr = document.createElement('tr'); + tbody.appendChild(tr); + const renderRow = new Array(dataRow.length); + this._renderCells[r] = renderRow; + for (let c = 0; c < dataRow.length; c++) { + const dataCell = dataRow[c]; + const renderCell = document.createElement('td'); + if (r % 2 === 0) { + renderCell.style.backgroundColor = 'grey'; + } + tr.appendChild(renderCell); + renderRow[c] = renderCell; + this._updateCell(renderCell, dataCell); + } + } + } +} diff --git a/modules/benchmarks/src/largetable/incremental_dom/index.html b/modules/benchmarks/src/largetable/incremental_dom/index.html new file mode 100644 index 0000000000..9688ff7156 --- /dev/null +++ b/modules/benchmarks/src/largetable/incremental_dom/index.html @@ -0,0 +1,30 @@ + + + + +

Params

+
+ Cols: + +
+ Rows: + +
+ +
+ +

Incremental-Dom Largetable Benchmark

+

+ + + + +

+ +
+ +
+ + + + \ No newline at end of file diff --git a/modules/benchmarks/src/largetable/incremental_dom/index.ts b/modules/benchmarks/src/largetable/incremental_dom/index.ts new file mode 100644 index 0000000000..d3458cd310 --- /dev/null +++ b/modules/benchmarks/src/largetable/incremental_dom/index.ts @@ -0,0 +1,25 @@ +import {bindAction, profile} from '../../util'; +import {buildTable, emptyTable} from '../util'; +import {TableComponent} from './table'; + +export function main() { + var table: TableComponent; + + function destroyDom() { table.data = emptyTable; } + + function createDom() { table.data = buildTable(); } + + function noop() {} + + function init() { + table = new TableComponent(document.querySelector('largetable')); + + 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/largetable/incremental_dom/table.ts b/modules/benchmarks/src/largetable/incremental_dom/table.ts new file mode 100644 index 0000000000..1ea8ea40a1 --- /dev/null +++ b/modules/benchmarks/src/largetable/incremental_dom/table.ts @@ -0,0 +1,30 @@ +import {TableCell} from '../util'; +const {patch, elementOpen, elementClose, elementOpenStart, elementOpenEnd, attr, text} = + require('incremental-dom'); + +export class TableComponent { + constructor(private _rootEl: any) {} + + set data(data: TableCell[][]) { patch(this._rootEl, () => this._render(data)); } + + private _render(data: TableCell[][]) { + elementOpen('table'); + elementOpen('tbody'); + for (let r = 0; r < data.length; r++) { + elementOpen('tr'); + const row = data[r]; + for (let c = 0; c < row.length; c++) { + elementOpenStart('td'); + if (r % 2 === 0) { + attr('style', 'background-color: grey'); + } + elementOpenEnd('td'); + text(row[c].value); + elementClose('td'); + } + elementClose('tr'); + } + elementClose('tbody'); + elementClose('table'); + } +} diff --git a/modules/benchmarks/src/largetable/ng2/index.html b/modules/benchmarks/src/largetable/ng2/index.html new file mode 100644 index 0000000000..37b72355b4 --- /dev/null +++ b/modules/benchmarks/src/largetable/ng2/index.html @@ -0,0 +1,30 @@ + + + + +

Params

+
+ Cols: + +
+ Rows: + +
+ +
+ +

Ng2 Largetable Benchmark

+

+ + + + +

+ +
+ +
+ + + + diff --git a/modules/benchmarks/src/largetable/ng2/index.ts b/modules/benchmarks/src/largetable/ng2/index.ts new file mode 100644 index 0000000000..0d23ca369c --- /dev/null +++ b/modules/benchmarks/src/largetable/ng2/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 {buildTable, emptyTable} from '../util'; + +import {AppModule, TableComponent} from './table'; + +export function main() { + var table: TableComponent; + var appRef: ApplicationRef; + + function destroyDom() { + table.data = emptyTable; + appRef.tick(); + } + + function createDom() { + table.data = buildTable(); + appRef.tick(); + } + + function noop() {} + + function init() { + enableProdMode(); + platformBrowserDynamic().bootstrapModule(AppModule).then((ref) => { + var injector = ref.injector; + appRef = injector.get(ApplicationRef); + + table = 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/largetable/ng2/table.ts b/modules/benchmarks/src/largetable/ng2/table.ts new file mode 100644 index 0000000000..dc3a07be0a --- /dev/null +++ b/modules/benchmarks/src/largetable/ng2/table.ts @@ -0,0 +1,20 @@ +import {Component, Input, NgModule} from '@angular/core'; +import {BrowserModule} from '@angular/platform-browser'; + +import {TableCell, emptyTable} from '../util'; + +@Component({ + selector: 'largetable', + template: + `
{{cell.value}}
` +}) +export class TableComponent { + @Input() + data: TableCell[][] = emptyTable; + + trackByIndex(index: number, item: any) { return index; } +} + +@NgModule({imports: [BrowserModule], bootstrap: [TableComponent], declarations: [TableComponent]}) +export class AppModule { +} diff --git a/modules/benchmarks/src/largetable/ng2_switch/index.html b/modules/benchmarks/src/largetable/ng2_switch/index.html new file mode 100644 index 0000000000..fdf0f45aaa --- /dev/null +++ b/modules/benchmarks/src/largetable/ng2_switch/index.html @@ -0,0 +1,30 @@ + + + + +

Params

+
+ Cols: + +
+ Rows: + +
+ +
+ +

Ng2 with NgSwitch Largetable Benchmark

+

+ + + + +

+ +
+ +
+ + + + diff --git a/modules/benchmarks/src/largetable/ng2_switch/index.ts b/modules/benchmarks/src/largetable/ng2_switch/index.ts new file mode 100644 index 0000000000..0d23ca369c --- /dev/null +++ b/modules/benchmarks/src/largetable/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 {buildTable, emptyTable} from '../util'; + +import {AppModule, TableComponent} from './table'; + +export function main() { + var table: TableComponent; + var appRef: ApplicationRef; + + function destroyDom() { + table.data = emptyTable; + appRef.tick(); + } + + function createDom() { + table.data = buildTable(); + appRef.tick(); + } + + function noop() {} + + function init() { + enableProdMode(); + platformBrowserDynamic().bootstrapModule(AppModule).then((ref) => { + var injector = ref.injector; + appRef = injector.get(ApplicationRef); + + table = 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/largetable/ng2_switch/table.ts b/modules/benchmarks/src/largetable/ng2_switch/table.ts new file mode 100644 index 0000000000..0ab2f7df6e --- /dev/null +++ b/modules/benchmarks/src/largetable/ng2_switch/table.ts @@ -0,0 +1,25 @@ +import {Component, Input, NgModule} from '@angular/core'; +import {BrowserModule} from '@angular/platform-browser'; + +import {TableCell, emptyTable} from '../util'; + +@Component({ + selector: 'largetable', + template: ` + + +
` +}) +export class TableComponent { + @Input() + data: TableCell[][] = emptyTable; +} + +@NgModule({imports: [BrowserModule], bootstrap: [TableComponent], declarations: [TableComponent]}) +export class AppModule { +} diff --git a/modules/benchmarks/src/largetable/util.ts b/modules/benchmarks/src/largetable/util.ts new file mode 100644 index 0000000000..662f2cc132 --- /dev/null +++ b/modules/benchmarks/src/largetable/util.ts @@ -0,0 +1,42 @@ +import {getIntParameter} from '../util'; + +export class TableCell { + constructor(public row: number, public col: number, public value: string) {} +} + +let tableCreateCount: number; +export let maxRow: number; +export let maxCol: number; +let numberData: TableCell[][]; +let charData: TableCell[][]; + +init(); + +function init() { + maxRow = getIntParameter('rows'); + maxCol = getIntParameter('cols'); + tableCreateCount = 0; + numberData = []; + charData = []; + for (let r = 0; r <= maxRow; r++) { + const numberRow: TableCell[] = []; + numberData.push(numberRow); + const charRow: TableCell[] = []; + charData.push(charRow); + for (let c = 0; c <= maxCol; c++) { + numberRow.push(new TableCell(r, c, `${c}/${r}`)); + charRow.push(new TableCell(r, c, `${charValue(c)}/${charValue(r)}`)); + } + } +} + +function charValue(i: number): string { + return String.fromCharCode('A'.charCodeAt(0) + (i % 26)); +} + +export const emptyTable: TableCell[][] = []; + +export function buildTable(): TableCell[][] { + tableCreateCount++; + return tableCreateCount % 2 ? numberData : charData; +} diff --git a/modules/benchmarks/src/old/largetable/largetable_benchmark.html b/modules/benchmarks/src/old/largetable/largetable_benchmark.html deleted file mode 100644 index 1c49130c7f..0000000000 --- a/modules/benchmarks/src/old/largetable/largetable_benchmark.html +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - -

Params

- -
-
-
- Use Viewcache: - - -
- -
- rows: - - columns: - -
- -
- baseline (to be used in conjuction with Baseline:createDom & Baseline:destroyDom buttons): - -
-
- ngBind (not implemented): - -
-
- ngBindOnce (not implemented): - -
-
- interpolation: - -
-
- attribute interpolation: - -
-
- ngBind + fnInvocation (not implemented): - -
-
- interpolation + fnInvocation: - -
-
- ngBind + filter (not implemented): - -
-
- interpolation + filter (not implemented): - -
- -
-
- -

Angular2 largetable benchmark

-

- - - - -

- -

Baseline largetable benchmark

-

- - - - -

- -
- -
- -
- -
- -$SCRIPTS$ - - diff --git a/modules/benchmarks/src/old/largetable/largetable_benchmark.ts b/modules/benchmarks/src/old/largetable/largetable_benchmark.ts deleted file mode 100644 index c632d09315..0000000000 --- a/modules/benchmarks/src/old/largetable/largetable_benchmark.ts +++ /dev/null @@ -1,260 +0,0 @@ -import {NgFor, NgSwitch, NgSwitchCase, NgSwitchDefault} from '@angular/common'; -import {Component} from '@angular/core'; -import {ApplicationRef} from '@angular/core/src/application_ref'; -import {Inject} from '@angular/core/src/di/decorators'; -import {reflector} from '@angular/core/src/reflection/reflection'; -import {document, gc, window} from '@angular/facade/src/browser'; -import {ListWrapper} from '@angular/facade/src/collection'; -import {bootstrap} from '@angular/platform-browser'; -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'; - -export const BENCHMARK_TYPE = 'LargetableComponent.benchmarkType'; -export const LARGETABLE_ROWS = 'LargetableComponent.rows'; -export const LARGETABLE_COLS = 'LargetableComponent.cols'; - -function _createBindings() { - return [ - {provide: BENCHMARK_TYPE, useValue: getStringParameter('benchmarkType')}, - {provide: LARGETABLE_ROWS, useValue: getIntParameter('rows')}, - {provide: LARGETABLE_COLS, useValue: getIntParameter('columns')}, - ]; -} - -var BASELINE_LARGETABLE_TEMPLATE; - -function setupReflector() { - // TODO(kegluneq): Generate these. - reflector.registerGetters({ - 'benchmarktype': (o) => o.benchmarktype, - 'switch': (o) => null, - 'switchCase': (o) => o.switchCase - }); - reflector.registerSetters({ - 'benchmarktype': (o, v) => o.benchmarktype = v, - 'switch': (o, v) => null, - 'switchCase': (o, v) => o.switchCase = v - }); -} - -export function main() { - BrowserDomAdapter.makeCurrent(); - var totalRows = getIntParameter('rows'); - var totalColumns = getIntParameter('columns'); - BASELINE_LARGETABLE_TEMPLATE = DOM.createTemplate('
'); - - var app; - var appRef; - var baselineRootLargetableComponent; - - function ng2DestroyDom() { - // TODO: We need an initial value as otherwise the getter for data.value will fail - // --> this should be already caught in change detection! - app.data = null; - app.benchmarkType = 'none'; - appRef.tick(); - } - - 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 ng2CreateDom() { - var data = ListWrapper.createFixedSize(totalRows); - - for (var i = 0; i < totalRows; i++) { - data[i] = ListWrapper.createFixedSize(totalColumns); - for (var j = 0; j < totalColumns; j++) { - data[i][j] = new CellData(i, j); - } - } - app.data = data; - app.benchmarkType = getStringParameter('benchmarkType'); - appRef.tick(); - } - - function noop() {} - - function initNg2() { - bootstrap(AppComponent, _createBindings()).then((ref) => { - var injector = ref.injector; - app = ref.instance; - appRef = injector.get(ApplicationRef); - bindAction('#ng2DestroyDom', ng2DestroyDom); - bindAction('#ng2CreateDom', ng2CreateDom); - bindAction('#ng2UpdateDomProfile', profile(ng2CreateDom, noop, 'ng2-update')); - bindAction('#ng2CreateDomProfile', profile(ng2CreateDom, ng2DestroyDom, 'ng2-create')); - }); - setupReflector(); - } - - function baselineDestroyDom() { baselineRootLargetableComponent.update(buildTable(0, 0)); } - - function baselineCreateDom() { - baselineRootLargetableComponent.update(buildTable(totalRows, totalColumns)); - } - - function initBaseline() { - baselineRootLargetableComponent = new BaseLineLargetableComponent( - DOM.querySelector(document, 'baseline'), getStringParameter('benchmarkType'), - getIntParameter('rows'), getIntParameter('columns')); - - bindAction('#baselineDestroyDom', baselineDestroyDom); - bindAction('#baselineCreateDom', baselineCreateDom); - - bindAction('#baselineUpdateDomProfile', profile(baselineCreateDom, noop, 'baseline-update')); - bindAction( - '#baselineCreateDomProfile', - profile(baselineCreateDom, baselineDestroyDom, 'baseline-create')); - } - - initNg2(); - initBaseline(); -} - -function buildTable(rows, columns) { - var tbody = DOM.createElement('tbody'); - var template = DOM.createElement('span'); - var i, j, row, cell; - DOM.appendChild(template, DOM.createElement('span')); - DOM.appendChild(template, DOM.createTextNode(':')); - DOM.appendChild(template, DOM.createElement('span')); - DOM.appendChild(template, DOM.createTextNode('|')); - - for (i = 0; i < rows; i++) { - row = DOM.createElement('div'); - DOM.appendChild(tbody, row); - for (j = 0; j < columns; j++) { - cell = DOM.clone(template); - DOM.appendChild(row, cell); - DOM.setText(cell.childNodes[0], i.toString()); - DOM.setText(cell.childNodes[2], j.toString()); - } - } - - return tbody; -} - -class BaseLineLargetableComponent { - element; - table; - benchmarkType: string; - rows: number; - columns: number; - constructor(element, benchmarkType, rows: number, columns: number) { - this.element = element; - this.benchmarkType = benchmarkType; - this.rows = rows; - this.columns = columns; - this.table = DOM.clone(BASELINE_LARGETABLE_TEMPLATE.content.firstChild); - var shadowRoot = DOM.createShadowRoot(this.element); - DOM.appendChild(shadowRoot, this.table); - } - update(tbody) { - var oldBody = DOM.querySelector(this.table, 'tbody'); - if (oldBody != null) { - DOM.replaceChild(this.table, tbody, oldBody); - } else { - DOM.appendChild(this.table, tbody); - } - } -} - -class CellData { - i: number; - j: number; - constructor(i, j) { - this.i = i; - this.j = j; - } - - jFn() { return this.j; } - - iFn() { return this.i; } -} - -@Component({ - selector: 'largetable', - inputs: ['data', 'benchmarkType'], - directives: [NgFor, NgSwitch, NgSwitchCase, NgSwitchDefault], - template: ` - - - - - - - - - - - - - - - - - - - - - -
- {{column.i}}:{{column.j}}| -
- i,j attrs -
- {{column.iFn()}}:{{column.jFn()}}| -
- {{benchmarkType}} not yet implemented -
` -}) -class LargetableComponent { - data; - benchmarkType: string; - rows: number; - columns: number; - constructor( - @Inject(BENCHMARK_TYPE) benchmarkType, @Inject(LARGETABLE_ROWS) rows, - @Inject(LARGETABLE_COLS) columns) { - this.benchmarkType = benchmarkType; - this.rows = rows; - this.columns = columns; - } -} - -@Component({ - selector: 'app', - directives: [LargetableComponent], - template: `` -}) -class AppComponent { - data; - benchmarkType: string; -}