refactor(benchamrks_external): Ts'ify benchmarks_external

Translates benchmarks_external to TypeScript.
This commit is contained in:
Ian Riley 2015-06-03 10:04:27 -07:00
parent 4d0973d7ba
commit b2596dd302
24 changed files with 441 additions and 466 deletions

View File

@ -0,0 +1,3 @@
library benchmarks_external.e2e_test.compiler_perf;
main() {}

View File

@ -1,30 +1,26 @@
var perfUtil = require('angular2/src/test_lib/perf_util');
import {runClickBenchmark, verifyNoBrowserErrors} from 'angular2/src/test_lib/perf_util';
describe('ng1.x compiler benchmark', function() {
var URL = 'benchmarks_external/src/compiler/compiler_benchmark.html';
afterEach(perfUtil.verifyNoBrowserErrors);
afterEach(verifyNoBrowserErrors);
it('should log withBinding stats', function(done) {
perfUtil.runClickBenchmark({
runClickBenchmark({
url: URL,
buttons: ['#compileWithBindings'],
id: 'ng1.compile.withBindings',
params: [{
name: 'elements', value: 150, scale: 'linear'
}]
params: [{name: 'elements', value: 150, scale: 'linear'}]
}).then(done, done.fail);
});
it('should log noBindings stats', function(done) {
perfUtil.runClickBenchmark({
runClickBenchmark({
url: URL,
buttons: ['#compileNoBindings'],
id: 'ng1.compile.noBindings',
params: [{
name: 'elements', value: 150, scale: 'linear'
}]
params: [{name: 'elements', value: 150, scale: 'linear'}]
}).then(done, done.fail);
});

View File

@ -0,0 +1,3 @@
library benchmarks_external.e2e_test.largetable_perf;
main() {}

View File

@ -1,40 +0,0 @@
var perfUtil = require('angular2/src/test_lib/perf_util');
describe('ng1.x largetable benchmark', function () {
var URL = 'benchmarks_external/src/largetable/largetable_benchmark.html';
afterEach(perfUtil.verifyNoBrowserErrors);
[
'baselineBinding',
'baselineInterpolation',
'ngBind',
'ngBindOnce',
'interpolation',
'interpolationAttr',
'ngBindFn',
'interpolationFn',
'ngBindFilter',
'interpolationFilter'
].forEach(function(benchmarkType) {
it('should log the stats with: ' + benchmarkType, function(done) {
perfUtil.runClickBenchmark({
url: URL,
buttons: ['#destroyDom', '#createDom'],
id: 'ng1.largetable.' + benchmarkType,
params: [{
name: 'columns',
value: 100,
scale: 'sqrt'
},{
name: 'rows',
value: 20,
scale: 'sqrt'
},{
name: 'benchmarkType',
value: benchmarkType
}]
}).then(done, done.fail);
});
});
});

View File

@ -0,0 +1,24 @@
import {runClickBenchmark, verifyNoBrowserErrors} from 'angular2/src/test_lib/perf_util';
describe('ng1.x largetable benchmark', function() {
var URL = 'benchmarks_external/src/largetable/largetable_benchmark.html';
afterEach(verifyNoBrowserErrors);
['baselineBinding', 'baselineInterpolation', 'ngBind', 'ngBindOnce', 'interpolation',
'interpolationAttr', 'ngBindFn', 'interpolationFn', 'ngBindFilter', 'interpolationFilter']
.forEach(function(benchmarkType) {
it('should log the stats with: ' + benchmarkType, function(done) {
runClickBenchmark({
url: URL,
buttons: ['#destroyDom', '#createDom'],
id: 'ng1.largetable.' + benchmarkType,
params: [
{name: 'columns', value: 100, scale: 'sqrt'},
{name: 'rows', value: 20, scale: 'sqrt'},
{name: 'benchmarkType', value: benchmarkType}
]
}).then(done, done.fail);
});
});
});

View File

@ -0,0 +1,3 @@
library benchmarks_external.e2e_test.naive_infinite_scroll_perf;
main() {}

View File

@ -1,15 +1,14 @@
var perfUtil = require('angular2/src/test_lib/perf_util');
import {runBenchmark, verifyNoBrowserErrors} from 'angular2/src/test_lib/perf_util';
describe('ng-dart1.x naive infinite scroll benchmark', function() {
var URL = 'benchmarks_external/src/naive_infinite_scroll/index.html';
afterEach(perfUtil.verifyNoBrowserErrors);
afterEach(verifyNoBrowserErrors);
[1, 2, 4].forEach(function(appSize) {
it('should run scroll benchmark and collect stats for appSize = ' +
appSize, function(done) {
perfUtil.runBenchmark({
it('should run scroll benchmark and collect stats for appSize = ' + appSize, function(done) {
runBenchmark({
url: URL,
id: 'ng1-dart1.x.naive_infinite_scroll',
work: function() {
@ -21,13 +20,11 @@ describe('ng-dart1.x naive infinite scroll benchmark', function () {
}
browser.sleep(s);
},
params: [{
name: 'appSize', value: appSize
}, {
name: 'iterationCount', value: 20, scale: 'linear'
}, {
name: 'scrollIncrement', value: 40
}]
params: [
{name: 'appSize', value: appSize},
{name: 'iterationCount', value: 20, scale: 'linear'},
{name: 'scrollIncrement', value: 40}
]
}).then(done, done.fail);
});
});

View File

@ -0,0 +1,3 @@
library benchmarks_external.e2e_test.polymer_tree_perf;
main() {}

View File

@ -1,20 +0,0 @@
var perfUtil = require('angular2/src/test_lib/perf_util');
describe('polymer tree benchmark', function () {
var URL = 'benchmarks_external/src/tree/polymer/index.html';
afterEach(perfUtil.verifyNoBrowserErrors);
it('should log the stats', function(done) {
perfUtil.runClickBenchmark({
url: URL,
buttons: ['#destroyDom', '#createDom'],
id: 'polymer.tree',
params: [{
name: 'depth', value: 9, scale: 'log2'
}]
}).then(done, done.fail);
});
});

View File

@ -0,0 +1,18 @@
import {runClickBenchmark, verifyNoBrowserErrors} from 'angular2/src/test_lib/perf_util';
describe('polymer tree benchmark', function() {
var URL = 'benchmarks_external/src/tree/polymer/index.html';
afterEach(verifyNoBrowserErrors);
it('should log the stats', function(done) {
runClickBenchmark({
url: URL,
buttons: ['#destroyDom', '#createDom'],
id: 'polymer.tree',
params: [{name: 'depth', value: 9, scale: 'log2'}]
}).then(done, done.fail);
});
});

View File

@ -0,0 +1,3 @@
library benchmarks_external.e2e_test.react_tree_perf;
main() {}

View File

@ -1,30 +1,26 @@
var perfUtil = require('angular2/src/test_lib/perf_util');
import {runClickBenchmark, verifyNoBrowserErrors} from 'angular2/src/test_lib/perf_util';
describe('react tree benchmark', function() {
var URL = 'benchmarks_external/src/tree/react/index.html';
afterEach(perfUtil.verifyNoBrowserErrors);
afterEach(verifyNoBrowserErrors);
it('should log the stats (create)', function(done) {
perfUtil.runClickBenchmark({
runClickBenchmark({
url: URL,
buttons: ['#destroyDom', '#createDom'],
id: 'react.tree.create',
params: [{
name: 'depth', value: 9, scale: 'log2'
}]
params: [{name: 'depth', value: 9, scale: 'log2'}]
}).then(done, done.fail);
});
it('should log the stats (update)', function(done) {
perfUtil.runClickBenchmark({
runClickBenchmark({
url: URL,
buttons: ['#createDom'],
id: 'react.tree.update',
params: [{
name: 'depth', value: 9, scale: 'log2'
}]
params: [{name: 'depth', value: 9, scale: 'log2'}]
}).then(done, done.fail);
});

View File

@ -0,0 +1,3 @@
library benchmarks_external.e2e_test.tree_perf;
main() {}

View File

@ -1,20 +0,0 @@
var perfUtil = require('angular2/src/test_lib/perf_util');
describe('ng1.x tree benchmark', function () {
var URL = 'benchmarks_external/src/tree/tree_benchmark.html';
afterEach(perfUtil.verifyNoBrowserErrors);
it('should log the stats', function(done) {
perfUtil.runClickBenchmark({
url: URL,
buttons: ['#destroyDom', '#createDom'],
id: 'ng1.tree',
params: [{
name: 'depth', value: 9, scale: 'log2'
}]
}).then(done, done.fail);
});
});

View File

@ -0,0 +1,18 @@
import {runClickBenchmark, verifyNoBrowserErrors} from 'angular2/src/test_lib/perf_util';
describe('ng1.x tree benchmark', function() {
var URL = 'benchmarks_external/src/tree/tree_benchmark.html';
afterEach(verifyNoBrowserErrors);
it('should log the stats', function(done) {
runClickBenchmark({
url: URL,
buttons: ['#destroyDom', '#createDom'],
id: 'ng1.tree',
params: [{name: 'depth', value: 9, scale: 'log2'}]
}).then(done, done.fail);
});
});

View File

@ -1,96 +0,0 @@
// compiler benchmark in AngularJS 1.x
import {getIntParameter, bindAction} from 'angular2/src/test_lib/benchmark_util';
export function main() {
var ngEl = document.createElement('div');
angular.bootstrap(ngEl, ['app']);
}
function loadTemplate(templateId, repeatCount) {
var template = document.querySelectorAll(`#${templateId}`)[0];
var content = template.innerHTML;
var result = '';
for (var i=0; i<repeatCount; i++) {
result += content;
}
// replace [] binding syntax
result = result.replace(/[\[\]]/g, '');
// Use a DIV as container as Angular 1.3 does not know <template> elements...
var div = document.createElement('div');
div.innerHTML = result;
return div;
}
angular.module('app', [])
.directive('dir0', ['$parse', function($parse) {
return {
compile: function($element, $attrs) {
var expr = $parse($attrs.attr0);
return function($scope) {
$scope.$watch(expr, angular.noop);
}
}
};
}])
.directive('dir1', ['$parse', function($parse) {
return {
compile: function($element, $attrs) {
var expr = $parse($attrs.attr1);
return function($scope) {
$scope.$watch(expr, angular.noop);
}
}
};
}])
.directive('dir2', ['$parse', function($parse) {
return {
compile: function($element, $attrs) {
var expr = $parse($attrs.attr2);
return function($scope) {
$scope.$watch(expr, angular.noop);
}
}
};
}])
.directive('dir3', ['$parse', function($parse) {
return {
compile: function($element, $attrs) {
var expr = $parse($attrs.attr3);
return function($scope) {
$scope.$watch(expr, angular.noop);
}
}
};
}])
.directive('dir4', ['$parse', function($parse) {
return {
compile: function($element, $attrs) {
var expr = $parse($attrs.attr4);
return function($scope) {
$scope.$watch(expr, angular.noop);
}
}
};
}])
.run(['$compile', function($compile) {
var count = getIntParameter('elements');
var templateNoBindings = loadTemplate('templateNoBindings', count);
var templateWithBindings = loadTemplate('templateWithBindings', count);
bindAction('#compileWithBindings', compileWithBindings);
bindAction('#compileNoBindings', compileNoBindings);
function compileNoBindings() {
// Need to clone every time as the compiler might modify the template!
var cloned = templateNoBindings.cloneNode(true);
$compile(cloned);
}
function compileWithBindings() {
// Need to clone every time as the compiler might modify the template!
var cloned = templateWithBindings.cloneNode(true);
$compile(cloned);
}
}]);

View File

@ -0,0 +1,104 @@
// compiler benchmark in AngularJS 1.x
import {getIntParameter, bindAction} from 'angular2/src/test_lib/benchmark_util';
import angular = require("angular");
export function main() {
var ngEl = document.createElement('div');
angular.bootstrap(ngEl, ['app']);
}
function loadTemplate(templateId, repeatCount) {
var template = document.querySelectorAll(`#${templateId}`)[0];
var content = template.innerHTML;
var result = '';
for (var i = 0; i < repeatCount; i++) {
result += content;
}
// replace [] binding syntax
result = result.replace(/[\[\]]/g, '');
// Use a DIV as container as Angular 1.3 does not know <template> elements...
var div = document.createElement('div');
div.innerHTML = result;
return div;
}
angular.module('app', [])
.directive('dir0', [
'$parse',
function($parse) {
return {
compile: function($element, $attrs) {
var expr = $parse($attrs.attr0);
return function($scope) { $scope.$watch(expr, angular.noop); }
}
};
}
])
.directive('dir1', [
'$parse',
function($parse) {
return {
compile: function($element, $attrs) {
var expr = $parse($attrs.attr1);
return function($scope) { $scope.$watch(expr, angular.noop); }
}
};
}
])
.directive('dir2', [
'$parse',
function($parse) {
return {
compile: function($element, $attrs) {
var expr = $parse($attrs.attr2);
return function($scope) { $scope.$watch(expr, angular.noop); }
}
};
}
])
.directive('dir3', [
'$parse',
function($parse) {
return {
compile: function($element, $attrs) {
var expr = $parse($attrs.attr3);
return function($scope) { $scope.$watch(expr, angular.noop); }
}
};
}
])
.directive('dir4', [
'$parse',
function($parse) {
return {
compile: function($element, $attrs) {
var expr = $parse($attrs.attr4);
return function($scope) { $scope.$watch(expr, angular.noop); }
}
};
}
])
.run([
'$compile',
function($compile) {
var count = getIntParameter('elements');
var templateNoBindings = loadTemplate('templateNoBindings', count);
var templateWithBindings = loadTemplate('templateWithBindings', count);
bindAction('#compileWithBindings', compileWithBindings);
bindAction('#compileNoBindings', compileNoBindings);
function compileNoBindings() {
// Need to clone every time as the compiler might modify the template!
var cloned = templateNoBindings.cloneNode(true);
$compile(cloned);
}
function compileWithBindings() {
// Need to clone every time as the compiler might modify the template!
var cloned = templateWithBindings.cloneNode(true);
$compile(cloned);
}
}
]);

View File

@ -0,0 +1 @@
library benchmarks_external.src.largetable;

View File

@ -1,119 +0,0 @@
import {getIntParameter, getStringParameter, bindAction} from 'angular2/src/test_lib/benchmark_util';
var totalRows = getIntParameter('rows');
var totalColumns = getIntParameter('columns');
var benchmarkType = getStringParameter('benchmarkType');
export function main() {
angular.bootstrap(document.querySelector('largetable'), ['app']);
}
angular.module('app', [])
.config(function($compileProvider) {
if ($compileProvider.debugInfoEnabled) {
$compileProvider.debugInfoEnabled(false);
}
})
.filter('noop', function() {
return function(input) {
return input;
};
})
.directive('largetable', function() {
return {
restrict: 'E',
templateUrl: 'largetable-js-template.html',
controller: 'DataController'
};
})
.controller('DataController', function($scope) {
bindAction('#destroyDom', destroyDom);
bindAction('#createDom', createDom);
function destroyDom() {
$scope.$apply(function() {
$scope.benchmarkType = 'none';
});
}
function createDom() {
$scope.$apply(function() {
$scope.benchmarkType = benchmarkType;
});
}
var data = $scope.data = [];
function iGetter() { return this.i; }
function jGetter() { return this.j; }
for (var i=0; i<totalRows; i++) {
data[i] = [];
for (var j=0; j<totalColumns; j++) {
data[i][j] = {
i: i, j: j,
iFn: iGetter,
jFn: jGetter
};
}
}
})
.directive('baselineBindingTable', function() {
return {
restrict: 'E',
link: function ($scope, $element) {
var i, j, row, cell, comment;
var template = document.createElement('span');
template.setAttribute('ng-repeat', 'foo in foos');
template.classList.add('ng-scope');
template.appendChild(document.createElement('span'));
template.appendChild(document.createTextNode(':'));
template.appendChild(document.createElement('span'));
template.appendChild(document.createTextNode('|'));
for (i = 0; i < totalRows; i++) {
row = document.createElement('div');
$element[0].appendChild(row);
for (j = 0; j < totalColumns; j++) {
cell = template.cloneNode(true);
row.appendChild(cell);
cell.childNodes[0].textContent = i;
cell.childNodes[2].textContent = j;
cell.ng3992 = 'xxx';
comment = document.createComment('ngRepeat end: bar in foo');
row.appendChild(comment);
}
comment = document.createComment('ngRepeat end: foo in foos');
$element[0].appendChild(comment);
}
}
};
})
.directive('baselineInterpolationTable', function() {
return {
restrict: 'E',
link: function ($scope, $element) {
var i, j, row, cell, comment;
var template = document.createElement('span');
template.setAttribute('ng-repeat', 'foo in foos');
template.classList.add('ng-scope');
for (i = 0; i < totalRows; i++) {
row = document.createElement('div');
$element[0].appendChild(row);
for (j = 0; j < totalColumns; j++) {
cell = template.cloneNode(true);
row.appendChild(cell);
cell.textContent = '' + i + ':' + j + '|';
cell.ng3992 = 'xxx';
comment = document.createComment('ngRepeat end: bar in foo');
row.appendChild(comment);
}
comment = document.createComment('ngRepeat end: foo in foos');
$element[0].appendChild(comment);
}
}
};
})

View File

@ -0,0 +1,120 @@
import {
getIntParameter,
getStringParameter,
bindAction
} from 'angular2/src/test_lib/benchmark_util';
import angular = require("angular");
var totalRows = getIntParameter('rows');
var totalColumns = getIntParameter('columns');
var benchmarkType = getStringParameter('benchmarkType');
export function main() {
angular.bootstrap(document.querySelector('largetable'), ['app']);
}
angular.module('app', [])
.config(function($compileProvider) {
if ($compileProvider.debugInfoEnabled) {
$compileProvider.debugInfoEnabled(false);
}
})
.filter('noop', function() { return function(input) { return input; }; })
.directive('largetable',
function() {
return {
restrict: 'E',
templateUrl: 'largetable-js-template.html',
controller: 'DataController'
};
})
.controller('DataController',
function($scope) {
bindAction('#destroyDom', destroyDom);
bindAction('#createDom', createDom);
function destroyDom() {
$scope.$apply(function() { $scope.benchmarkType = 'none'; });
}
function createDom() {
$scope.$apply(function() { $scope.benchmarkType = benchmarkType; });
}
var data = $scope.data = [];
function iGetter() { return this.i; }
function jGetter() { return this.j; }
for (var i = 0; i < totalRows; i++) {
data[i] = [];
for (var j = 0; j < totalColumns; j++) {
data[i][j] = {
i: i,
j: j,
iFn: iGetter,
jFn: jGetter
};
}
}
})
.directive('baselineBindingTable',
function() {
return {
restrict: 'E',
link: function($scope, $element) {
var i, j, row, cell, comment;
var template = document.createElement('span');
template.setAttribute('ng-repeat', 'foo in foos');
template.classList.add('ng-scope');
template.appendChild(document.createElement('span'));
template.appendChild(document.createTextNode(':'));
template.appendChild(document.createElement('span'));
template.appendChild(document.createTextNode('|'));
for (i = 0; i < totalRows; i++) {
row = document.createElement('div');
$element[0].appendChild(row);
for (j = 0; j < totalColumns; j++) {
cell = template.cloneNode(true);
row.appendChild(cell);
cell.childNodes[0].textContent = i;
cell.childNodes[2].textContent = j;
cell.ng3992 = 'xxx';
comment = document.createComment('ngRepeat end: bar in foo');
row.appendChild(comment);
}
comment = document.createComment('ngRepeat end: foo in foos');
$element[0].appendChild(comment);
}
}
};
})
.directive('baselineInterpolationTable', function() {
return {
restrict: 'E',
link: function($scope, $element) {
var i, j, row, cell, comment;
var template = document.createElement('span');
template.setAttribute('ng-repeat', 'foo in foos');
template.classList.add('ng-scope');
for (i = 0; i < totalRows; i++) {
row = document.createElement('div');
$element[0].appendChild(row);
for (j = 0; j < totalColumns; j++) {
cell = template.cloneNode(true);
row.appendChild(cell);
cell.textContent = '' + i + ':' + j + '|';
cell.ng3992 = 'xxx';
comment = document.createComment('ngRepeat end: bar in foo');
row.appendChild(comment);
}
comment = document.createComment('ngRepeat end: foo in foos');
$element[0].appendChild(comment);
}
}
};
})

View File

@ -0,0 +1 @@
library benchmarks_external.src.tree.react;

View File

@ -11,30 +11,18 @@ var TreeComponent = React.createClass({
var left = null;
if (treeNode.left) {
left = React.createElement(
"span",
{},
[React.createElement(TreeComponent, {treeNode: treeNode.left}, "")]
)
"span", {}, [React.createElement(TreeComponent, {treeNode: treeNode.left}, "")])
}
var right = null;
if (treeNode.right) {
right = React.createElement(
"span",
{},
[React.createElement(TreeComponent, {treeNode: treeNode.right}, "")]
)
"span", {}, [React.createElement(TreeComponent, {treeNode: treeNode.right}, "")])
}
var span = React.createElement("span", {}, [
" " + treeNode.value,
left,
right
]);
var span = React.createElement("span", {}, [" " + treeNode.value, left, right]);
return (
React.createElement("tree", {}, [span])
);
return (React.createElement("tree", {}, [span]));
}
});
@ -46,18 +34,13 @@ export function main() {
bindAction('#createDom', createDom);
var empty = new TreeNode(0, null, null);
var rootComponent = React.render(
React.createElement(TreeComponent, {treeNode: empty}, ""),
document.getElementById('rootTree')
);
var rootComponent = React.render(React.createElement(TreeComponent, {treeNode: empty}, ""),
document.getElementById('rootTree'));
function destroyDom() {
rootComponent.setProps({treeNode: empty});
}
function destroyDom() { rootComponent.setProps({treeNode: empty}); }
function createDom() {
var values = count++ % 2 == 0 ?
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '*'] :
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', '-'];
rootComponent.setProps({treeNode: buildTree(maxDepth, values, 0)});
}
@ -77,8 +60,6 @@ class TreeNode {
function buildTree(maxDepth, values, curDepth) {
if (maxDepth === curDepth) return new TreeNode('', null, null);
return new TreeNode(
values[curDepth],
buildTree(maxDepth, values, curDepth + 1),
return new TreeNode(values[curDepth], buildTree(maxDepth, values, curDepth + 1),
buildTree(maxDepth, values, curDepth + 1));
}

View File

@ -1,102 +0,0 @@
// tree benchmark in AngularJS 1.x
import {getIntParameter, bindAction} from 'angular2/src/test_lib/benchmark_util';
export function main() {
angular.bootstrap(document.querySelector('tree'), ['app']);
}
angular.module('app', [])
.directive('tree', function() {
return {
scope: {
data: '='
},
template:
'<span> {{data.value}}'+
' <span tree-if="data.left"></span>'+
' <span tree-if="data.right"></span>'+
'</span>'
};
})
// special directive for "if" as angular 1.3 does not support
// recursive components.
.directive('treeIf', ['$compile', '$parse', function($compile, $parse) {
var transcludeFn;
return {
compile: function(element, attrs) {
var expr = $parse(attrs.treeIf);
var template = '<tree data="'+attrs.treeIf+'"></tree>';
var transclude;
return function($scope, $element, $attrs) {
if (!transclude) {
transclude = $compile(template);
}
var childScope;
var childElement;
$scope.$watch(expr, function(newValue) {
if (childScope) {
childScope.$destroy();
childElement.remove();
childScope = null;
childElement = null;
}
if (newValue) {
childScope = $scope.$new();
childElement = transclude(childScope, function(clone) {
$element.append(clone);
});
}
});
}
}
}
}])
.config(['$compileProvider', function($compileProvider) {
$compileProvider.debugInfoEnabled(false);
}])
.run(['$rootScope', function($rootScope) {
var count = 0;
var maxDepth = getIntParameter('depth');
bindAction('#destroyDom', destroyDom);
bindAction('#createDom', createDom);
function destroyDom() {
$rootScope.$apply(function() {
$rootScope.initData = new TreeNode('', null, null);
});
}
function createDom() {
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', '-'];
$rootScope.$apply(function() {
$rootScope.initData = buildTree(maxDepth, values, 0);
});
}
}]);
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));
}

View File

@ -0,0 +1,98 @@
// tree benchmark in AngularJS 1.x
import {getIntParameter, bindAction} from 'angular2/src/test_lib/benchmark_util';
import angular = require("angular");
export function main() {
angular.bootstrap(document.querySelector('tree'), ['app']);
}
angular.module('app', [])
.directive('tree',
function() {
return {
scope: {data: '='},
template: '<span> {{data.value}}' +
' <span tree-if="data.left"></span>' +
' <span tree-if="data.right"></span>' +
'</span>'
};
})
// special directive for "if" as angular 1.3 does not support
// recursive components.
.directive('treeIf', [
'$compile',
'$parse',
function($compile, $parse) {
var transcludeFn;
return {
compile: function(element, attrs) {
var expr = $parse(attrs.treeIf);
var template = '<tree data="' + attrs.treeIf + '"></tree>';
var transclude;
return function($scope, $element, $attrs) {
if (!transclude) {
transclude = $compile(template);
}
var childScope;
var childElement;
$scope.$watch(expr, function(newValue) {
if (childScope) {
childScope.$destroy();
childElement.remove();
childScope = null;
childElement = null;
}
if (newValue) {
childScope = $scope.$new();
childElement =
transclude(childScope, function(clone) { $element.append(clone); });
}
});
}
}
}
}
])
.config([
'$compileProvider',
function($compileProvider) { $compileProvider.debugInfoEnabled(false); }
])
.run([
'$rootScope',
function($rootScope) {
var count = 0;
var maxDepth = getIntParameter('depth');
bindAction('#destroyDom', destroyDom);
bindAction('#createDom', createDom);
function destroyDom() {
$rootScope.$apply(function() { $rootScope.initData = new TreeNode('', null, null); });
}
function createDom() {
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', '-'];
$rootScope.$apply(function() { $rootScope.initData = buildTree(maxDepth, values, 0); });
}
}
]);
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));
}