feat(benchmark): add static_tree benchmark
Static binary component tree of depth 10, i.e. 1024 components. Current numbers for `pureScriptTime` are: JavaScript: Baseline: 27.10+-9% Ng2: 26.84+-8% Ng1: 55.30+-14% Dart: Baseline: 30.13+-4% Ng2: 45.94+-3% Ng1: 128.88+-10% I.e. in JS we are same speed as baseline right now! Some background: We had a recent change in the compiler that merges components into their parents already during compilation (#2529). This made Ng2 2x faster in this benchmark (before the Ng2 JS time was 49.59+-14%ms). Closes #3196
This commit is contained in:
3
modules/benchmarks_external/e2e_test/static_tree.dart
Normal file
3
modules/benchmarks_external/e2e_test/static_tree.dart
Normal file
@ -0,0 +1,3 @@
|
||||
library benchmarks_external.e2e_test.static_tree_perf;
|
||||
|
||||
main() {}
|
15
modules/benchmarks_external/e2e_test/static_tree.ts
Normal file
15
modules/benchmarks_external/e2e_test/static_tree.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import {runClickBenchmark, verifyNoBrowserErrors} from 'angular2/src/test_lib/perf_util';
|
||||
|
||||
describe('ng1.x tree benchmark', function() {
|
||||
|
||||
var URL = 'benchmarks_external/src/static_tree/tree_benchmark.html';
|
||||
|
||||
afterEach(verifyNoBrowserErrors);
|
||||
|
||||
it('should log the stats', function(done) {
|
||||
runClickBenchmark(
|
||||
{url: URL, buttons: ['#destroyDom', '#createDom'], id: 'ng1.static.tree', params: []})
|
||||
.then(done, done.fail);
|
||||
});
|
||||
|
||||
});
|
@ -8,6 +8,9 @@
|
||||
<li>
|
||||
<a href="tree/tree_benchmark.html">Tree benchmark</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="static_tree/tree_benchmark.html">Static tree benchmark</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="tree/polymer/index.html">Polymer Tree benchmark</a>
|
||||
</li>
|
||||
|
164
modules/benchmarks_external/src/static_tree/tree_benchmark.dart
Normal file
164
modules/benchmarks_external/src/static_tree/tree_benchmark.dart
Normal file
@ -0,0 +1,164 @@
|
||||
// static tree benchmark in AngularDart 1.x
|
||||
library static_tree_benchmark_ng10;
|
||||
|
||||
import 'package:angular/angular.dart';
|
||||
import 'package:angular/application_factory.dart';
|
||||
import 'package:angular2/src/test_lib/benchmark_util.dart';
|
||||
|
||||
setup() {
|
||||
var m = new Module()
|
||||
..bind(CompilerConfig,
|
||||
toValue: new CompilerConfig.withOptions(elementProbeEnabled: false))
|
||||
..bind(ScopeDigestTTL,
|
||||
toFactory: () => new ScopeDigestTTL.value(15), inject: [])
|
||||
..bind(TreeComponent0)
|
||||
..bind(TreeComponent1)
|
||||
..bind(TreeComponent2)
|
||||
..bind(TreeComponent3)
|
||||
..bind(TreeComponent4)
|
||||
..bind(TreeComponent5)
|
||||
..bind(TreeComponent6)
|
||||
..bind(TreeComponent7)
|
||||
..bind(TreeComponent8)
|
||||
..bind(TreeComponent9);
|
||||
|
||||
final injector = applicationFactory().addModule(m).run();
|
||||
|
||||
return injector;
|
||||
}
|
||||
|
||||
const MAX_DEPTH = 10;
|
||||
|
||||
main() {
|
||||
final injector = setup();
|
||||
final zone = injector.get(VmTurnZone);
|
||||
final rootScope = injector.get(Scope);
|
||||
rootScope.context['initData'] = null;
|
||||
var count = 0;
|
||||
|
||||
TreeNode createData() {
|
||||
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);
|
||||
}
|
||||
|
||||
destroyDom() {
|
||||
zone.run(() {
|
||||
rootScope.context['initData'] = null;
|
||||
});
|
||||
}
|
||||
|
||||
createDom() {
|
||||
zone.run(() {
|
||||
rootScope.context['initData'] = createData();
|
||||
});
|
||||
}
|
||||
|
||||
bindAction('#destroyDom', destroyDom);
|
||||
bindAction('#createDom', createDom);
|
||||
}
|
||||
|
||||
@Component(
|
||||
selector: 'tree0',
|
||||
map: const {'data': '=>data'},
|
||||
template: '<span> {{data.value}} '
|
||||
)
|
||||
class TreeComponent0 {
|
||||
var data;
|
||||
}
|
||||
|
||||
@Component(
|
||||
selector: 'tree1',
|
||||
map: const {'data': '=>data'},
|
||||
template: '<span> {{data.value}} <tree0 data=data.right></tree0><tree0 data=data.left></tree0>'
|
||||
)
|
||||
class TreeComponent1 {
|
||||
var data;
|
||||
}
|
||||
|
||||
@Component(
|
||||
selector: 'tree2',
|
||||
map: const {'data': '=>data'},
|
||||
template: '<span> {{data.value}} <tree1 data=data.right></tree1><tree1 data=data.left></tree1>'
|
||||
)
|
||||
class TreeComponent2 {
|
||||
var data;
|
||||
}
|
||||
|
||||
@Component(
|
||||
selector: 'tree3',
|
||||
map: const {'data': '=>data'},
|
||||
template: '<span> {{data.value}} <tree2 data=data.right></tree2><tree2 data=data.left></tree2>'
|
||||
)
|
||||
class TreeComponent3 {
|
||||
var data;
|
||||
}
|
||||
|
||||
@Component(
|
||||
selector: 'tree4',
|
||||
map: const {'data': '=>data'},
|
||||
template: '<span> {{data.value}} <tree3 data=data.right></tree3><tree3 data=data.left></tree3>'
|
||||
)
|
||||
class TreeComponent4 {
|
||||
var data;
|
||||
}
|
||||
|
||||
@Component(
|
||||
selector: 'tree5',
|
||||
map: const {'data': '=>data'},
|
||||
template: '<span> {{data.value}} <tree4 data=data.right></tree4><tree4 data=data.left></tree4>'
|
||||
)
|
||||
class TreeComponent5 {
|
||||
var data;
|
||||
}
|
||||
|
||||
@Component(
|
||||
selector: 'tree6',
|
||||
map: const {'data': '=>data'},
|
||||
template: '<span> {{data.value}} <tree5 data=data.right></tree5><tree5 data=data.left></tree5>'
|
||||
)
|
||||
class TreeComponent6 {
|
||||
var data;
|
||||
}
|
||||
|
||||
@Component(
|
||||
selector: 'tree7',
|
||||
map: const {'data': '=>data'},
|
||||
template: '<span> {{data.value}} <tree6 data=data.right></tree6><tree6 data=data.left></tree6>'
|
||||
)
|
||||
class TreeComponent7 {
|
||||
var data;
|
||||
}
|
||||
|
||||
@Component(
|
||||
selector: 'tree8',
|
||||
map: const {'data': '=>data'},
|
||||
template: '<span> {{data.value}} <tree7 data=data.right></tree7><tree7 data=data.left></tree7>'
|
||||
)
|
||||
class TreeComponent8 {
|
||||
var data;
|
||||
}
|
||||
|
||||
@Component(
|
||||
selector: 'tree9',
|
||||
map: const {'data': '=>data'},
|
||||
template: '<span> {{data.value}} <tree8 data=data.right></tree8><tree8 data=data.left></tree8>'
|
||||
)
|
||||
class TreeComponent9 {
|
||||
var data;
|
||||
}
|
||||
|
||||
buildTree(maxDepth, values, curDepth) {
|
||||
if (maxDepth == curDepth) return new TreeNode('');
|
||||
return new TreeNode(values[curDepth],
|
||||
buildTree(maxDepth, values, curDepth + 1),
|
||||
buildTree(maxDepth, values, curDepth + 1));
|
||||
}
|
||||
|
||||
class TreeNode {
|
||||
var value;
|
||||
TreeNode left;
|
||||
TreeNode right;
|
||||
TreeNode([this.value, this.left, this.right]);
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<body>
|
||||
|
||||
<h2>AngularJS/Dart 1.x static tree benchmark (depth 10)</h2>
|
||||
<p>
|
||||
<button id="destroyDom">destroyDom</button>
|
||||
<button id="createDom">createDom</button>
|
||||
</p>
|
||||
|
||||
<div>
|
||||
<tree9 data="initData" ng-if="initData != null" class="app"></tree9>
|
||||
</div>
|
||||
|
||||
$SCRIPTS$
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,70 @@
|
||||
// static tree benchmark in AngularJS 1.x
|
||||
import {getIntParameter, bindAction} from 'angular2/src/test_lib/benchmark_util';
|
||||
import angular = require("angular");
|
||||
|
||||
const MAX_DEPTH = 10;
|
||||
|
||||
export function main() {
|
||||
angular.bootstrap(document.querySelector('.app'), ['app']);
|
||||
}
|
||||
|
||||
function addTreeDirective(module, level: number) {
|
||||
var template;
|
||||
if (level <= 0) {
|
||||
template = `<span> {{data.value}}</span>`
|
||||
} else {
|
||||
template =
|
||||
`<span> {{data.value}} <tree${level-1} data='data.right'></tree${level-1}><tree${level-1} data='data.left'></tree${level-1}></span>`;
|
||||
}
|
||||
module.directive(`tree${level}`, function() { return {scope: {data: '='}, template: template}; });
|
||||
}
|
||||
|
||||
var module = angular.module('app', []);
|
||||
for (var depth = 0; depth < MAX_DEPTH; depth++) {
|
||||
addTreeDirective(module, depth);
|
||||
}
|
||||
module.config([
|
||||
'$compileProvider',
|
||||
function($compileProvider) { $compileProvider.debugInfoEnabled(false); }
|
||||
])
|
||||
.run([
|
||||
'$rootScope',
|
||||
function($rootScope) {
|
||||
var count = 0;
|
||||
$rootScope.initData = null;
|
||||
|
||||
bindAction('#destroyDom', destroyDom);
|
||||
bindAction('#createDom', createDom);
|
||||
|
||||
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 destroyDom() {
|
||||
$rootScope.$apply(function() { $rootScope.initData = null; });
|
||||
}
|
||||
|
||||
function createDom() {
|
||||
$rootScope.$apply(function() { $rootScope.initData = createData(); });
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
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));
|
||||
}
|
Reference in New Issue
Block a user