benchmark(compiler): add a benchmark measuring view instantiation in AngularDart 1.0
This commit is contained in:
63
modules/benchmarks_external/src/benchpress.dart
Normal file
63
modules/benchmarks_external/src/benchpress.dart
Normal file
@ -0,0 +1,63 @@
|
||||
library benchmarks.benchpress;
|
||||
|
||||
import 'dart:js' as js;
|
||||
import 'dart:html';
|
||||
import 'dart:async';
|
||||
|
||||
// TODO: move the functionality of this module into benchpress and replace this
|
||||
// file with a Dart wrapper!
|
||||
|
||||
var _benchmarkNames = [];
|
||||
|
||||
_benchmarkId(index) {
|
||||
return "benchmark${index}";
|
||||
}
|
||||
|
||||
_useBenchmark(index) {
|
||||
var search = window.location.search;
|
||||
if (search.length > 0) {
|
||||
search = search.substring(1);
|
||||
}
|
||||
if (search.length > 0) {
|
||||
return search == _benchmarkId(index);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
_onLoad(callback) {
|
||||
var isReady = document.readyState == 'complete';
|
||||
if (isReady) {
|
||||
Timer.run(callback);
|
||||
} else {
|
||||
window.addEventListener('load', (event) => callback(), false);
|
||||
}
|
||||
}
|
||||
|
||||
_createBenchmarkMenu() {
|
||||
var div = document.createElement('div');
|
||||
div.innerHtml += '<h1>Benchmarks:</h1><a class="btn btn-default" href="?">All</a>';
|
||||
for (var i=0; i<_benchmarkNames.length; i++) {
|
||||
var activeClass = _useBenchmark(i) ? 'active' : '';
|
||||
div.innerHtml += '<a class="btn btn-default ${activeClass}" href="?${_benchmarkId(i)}">${_benchmarkNames[i]}</a>';
|
||||
}
|
||||
document.body.insertBefore(div, document.body.childNodes[0]);
|
||||
}
|
||||
|
||||
benchmark(name, stepsCreationCallback) {
|
||||
_benchmarkNames.add(name);
|
||||
if (_benchmarkNames.length == 2) {
|
||||
_onLoad(_createBenchmarkMenu);
|
||||
}
|
||||
if (_useBenchmark(_benchmarkNames.length-1)) {
|
||||
stepsCreationCallback();
|
||||
}
|
||||
}
|
||||
|
||||
benchmarkStep(name, callback) {
|
||||
var benchmarkName = _benchmarkNames[_benchmarkNames.length-1];
|
||||
js.context['benchmarkSteps'].add(new js.JsObject.jsify({
|
||||
"name": benchmarkName + '#' + name,
|
||||
"fn": new js.JsFunction.withThis((_) => callback())
|
||||
}));
|
||||
}
|
55
modules/benchmarks_external/src/benchpress.es6
Normal file
55
modules/benchmarks_external/src/benchpress.es6
Normal file
@ -0,0 +1,55 @@
|
||||
// TODO: move the functionality of this module into benchpress itself!
|
||||
|
||||
var benchmarkNames = [];
|
||||
|
||||
function benchmarkId(index) {
|
||||
return 'benchmark' + index;
|
||||
}
|
||||
|
||||
function useBenchmark(index) {
|
||||
var search = window.location.search;
|
||||
if (search.length > 0) {
|
||||
search = search.substring(1);
|
||||
}
|
||||
if (search.length > 0) {
|
||||
return search == benchmarkId(index);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function onLoad(callback) {
|
||||
var isReady = document.readyState === 'complete';
|
||||
if (isReady) {
|
||||
window.setTimeout(callback);
|
||||
} else {
|
||||
window.addEventListener('load', callback, false);
|
||||
}
|
||||
}
|
||||
|
||||
function createBenchmarkMenu() {
|
||||
var div = document.createElement('div');
|
||||
div.innerHTML += '<h1>Benchmarks:</h1><a class="btn btn-default" href="?">All</a>';
|
||||
for (var i=0; i<benchmarkNames.length; i++) {
|
||||
var activeClass = useBenchmark(i) ? 'active' : '';
|
||||
div.innerHTML += ('<a class="btn btn-default '+activeClass+'" href="?'+benchmarkId(i)+'">'+benchmarkNames[i]+'</a>');
|
||||
}
|
||||
document.body.insertBefore(div, document.body.childNodes[0]);
|
||||
}
|
||||
|
||||
export function benchmark(name, stepsCreationCallback) {
|
||||
benchmarkNames.push(name);
|
||||
if (benchmarkNames.length === 2) {
|
||||
onLoad(createBenchmarkMenu);
|
||||
}
|
||||
if (useBenchmark(benchmarkNames.length-1)) {
|
||||
stepsCreationCallback();
|
||||
}
|
||||
}
|
||||
|
||||
export function benchmarkStep(name, callback) {
|
||||
var benchmarkName = benchmarkNames[benchmarkNames.length-1];
|
||||
window.benchmarkSteps.push({
|
||||
name: benchmarkName + '#' + name, fn: callback
|
||||
});
|
||||
}
|
7
modules/benchmarks_external/src/compiler/benchmark.dart
Normal file
7
modules/benchmarks_external/src/compiler/benchmark.dart
Normal file
@ -0,0 +1,7 @@
|
||||
library compiler_benchmark;
|
||||
|
||||
import './compiler_benchmark_ng10.dart' as cbm;
|
||||
|
||||
main () {
|
||||
cbm.main();
|
||||
}
|
7
modules/benchmarks_external/src/compiler/benchmark.es5
Normal file
7
modules/benchmarks_external/src/compiler/benchmark.es5
Normal file
@ -0,0 +1,7 @@
|
||||
Promise.all([
|
||||
System.import('benchmarks_external/compiler/compiler_benchmark_ng13')
|
||||
]).then(function (benchmarks) {
|
||||
benchmarks.forEach(function(bm) {
|
||||
bm.main();
|
||||
});
|
||||
}, console.log.bind(console));
|
12
modules/benchmarks_external/src/compiler/bp.conf.es5
Normal file
12
modules/benchmarks_external/src/compiler/bp.conf.es5
Normal file
@ -0,0 +1,12 @@
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
scripts: [
|
||||
{src: '/js/traceur-runtime.js'},
|
||||
{src: '/js/es6-module-loader-sans-promises.src.js'},
|
||||
{src: '/js/extension-register.js'},
|
||||
{src: 'register_system.js'},
|
||||
{src: 'https://ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.js'},
|
||||
{src: 'benchmark.js'}
|
||||
]
|
||||
});
|
||||
};
|
@ -0,0 +1,175 @@
|
||||
import 'package:angular/angular.dart';
|
||||
import 'package:angular/application_factory_static.dart';
|
||||
import '../benchpress.dart';
|
||||
import 'dart:html';
|
||||
|
||||
var COUNT = 30;
|
||||
|
||||
main() {
|
||||
|
||||
final typeAnnotations = {
|
||||
Dir0: const [const Decorator(selector: '[dir0]', map: const {'attr0': '=>prop'})],
|
||||
Dir1: const [const Decorator(selector: '[dir1]', map: const {'attr1': '=>prop'})],
|
||||
Dir2: const [const Decorator(selector: '[dir2]', map: const {'attr2': '=>prop'})],
|
||||
Dir3: const [const Decorator(selector: '[dir3]', map: const {'attr3': '=>prop'})],
|
||||
Dir4: const [const Decorator(selector: '[dir4]', map: const {'attr4': '=>prop'})]
|
||||
};
|
||||
|
||||
final fieldGetters = {
|
||||
"inter0": (a) => a.inter0, "inter1": (a) => a.inter1,
|
||||
"inter2": (a) => a.inter2, "inter3": (a) => a.inter3, "inter4": (a) => a.inter4,
|
||||
|
||||
"value0": (a) => a.value0, "value1": (a) => a.value1,
|
||||
"value2": (a) => a.value2, "value3": (a) => a.value3, "value4": (a) => a.value4,
|
||||
|
||||
"prop" : (a) => a.prop
|
||||
};
|
||||
|
||||
final fieldSetters = {
|
||||
"inter0": (a,v) => a.inter0 = v, "inter1": (a,v) => a.inter1 = v,
|
||||
"inter2": (a,v) => a.inter2 = v, "inter3": (a,v) => a.inter3 = v, "inter4": (a,v) => a.inter4 = v,
|
||||
|
||||
"value0": (a,v) => a.value0 = v, "value1": (a,v) => a.value1 = v,
|
||||
"value2": (a,v) => a.value2 = v, "value3": (a,v) => a.value3 = v, "value4": (a,v) => a.value4 = v,
|
||||
|
||||
"prop": (a,v) => a.prop = v
|
||||
};
|
||||
|
||||
final symbols = {
|
||||
};
|
||||
|
||||
var m = new Module()
|
||||
..bind(Dir0)
|
||||
..bind(Dir1)
|
||||
..bind(Dir2)
|
||||
..bind(Dir3)
|
||||
..bind(Dir4);
|
||||
|
||||
benchmark("AngularDart 1.0 Compiler.compile 5*${COUNT} element with bindings", () {
|
||||
var template = loadTemplate('templateWithBindings', COUNT);
|
||||
|
||||
final injector = staticApplicationFactory(
|
||||
typeAnnotations,
|
||||
fieldGetters,
|
||||
fieldSetters,
|
||||
symbols
|
||||
).addModule(m).run();
|
||||
|
||||
final compiler = injector.get(Compiler);
|
||||
final directiveMap = injector.get(DirectiveMap);
|
||||
final di = injector.get(DirectiveInjector);
|
||||
final rootScope = injector.get(Scope);
|
||||
|
||||
benchmarkStep('run', () {
|
||||
final cloned = template.clone(true);
|
||||
final scope = rootScope.createChild({});
|
||||
final viewFactory = compiler([cloned], directiveMap);
|
||||
viewFactory(scope, di);
|
||||
scope.destroy();
|
||||
});
|
||||
});
|
||||
|
||||
benchmark("AngularDart 1.0 instantiate 5*${COUNT} element with bindings", () {
|
||||
var template = loadTemplate('templateWithBindings', COUNT);
|
||||
|
||||
final injector = staticApplicationFactory(
|
||||
typeAnnotations,
|
||||
fieldGetters,
|
||||
fieldSetters,
|
||||
symbols
|
||||
).addModule(m).run();
|
||||
|
||||
final compiler = injector.get(Compiler);
|
||||
final directiveMap = injector.get(DirectiveMap);
|
||||
final di = injector.get(DirectiveInjector);
|
||||
final rootScope = injector.get(Scope);
|
||||
final viewFactory = compiler([template], directiveMap);
|
||||
|
||||
benchmarkStep('run', () {
|
||||
var scope = rootScope.createChild({});
|
||||
viewFactory(scope, di);
|
||||
scope.destroy();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
loadTemplate(templateId, repeatCount) {
|
||||
String result = '';
|
||||
var content = document.querySelector("#${templateId}").innerHtml;
|
||||
for (var i=0; i<repeatCount; i++) {
|
||||
result += content;
|
||||
}
|
||||
return createTemplate(result.replaceAll(new RegExp(r'[\[\]]'), ''));
|
||||
}
|
||||
|
||||
class IdentitySanitizer implements NodeTreeSanitizer {
|
||||
void sanitizeTree(Node node) {}
|
||||
}
|
||||
|
||||
createTemplate(String html) {
|
||||
var div = document.createElement('div');
|
||||
div.setInnerHtml(html, treeSanitizer:new IdentitySanitizer());
|
||||
return div;
|
||||
}
|
||||
|
||||
@Decorator(
|
||||
selector: '[dir0]',
|
||||
map: const {
|
||||
'attr0': '=>prop'
|
||||
}
|
||||
)
|
||||
class Dir0 {
|
||||
Object prop;
|
||||
}
|
||||
|
||||
@Decorator(
|
||||
selector: '[dir1]',
|
||||
map: const {
|
||||
'attr1': '=>prop'
|
||||
}
|
||||
)
|
||||
class Dir1 {
|
||||
Object prop;
|
||||
|
||||
constructor(Dir0 dir0) {
|
||||
}
|
||||
}
|
||||
|
||||
@Decorator(
|
||||
selector: '[dir2]',
|
||||
map: const {
|
||||
'attr2': '=>prop'
|
||||
}
|
||||
)
|
||||
class Dir2 {
|
||||
Object prop;
|
||||
|
||||
constructor(Dir1 dir1) {
|
||||
}
|
||||
}
|
||||
|
||||
@Decorator(
|
||||
selector: '[dir3]',
|
||||
map: const {
|
||||
'attr3': '=>prop'
|
||||
}
|
||||
)
|
||||
class Dir3 {
|
||||
Object prop;
|
||||
|
||||
constructor(Dir2 dir2) {
|
||||
}
|
||||
}
|
||||
|
||||
@Decorator(
|
||||
selector: '[dir4]',
|
||||
map: const {
|
||||
'attr4': '=>prop'
|
||||
}
|
||||
)
|
||||
class Dir4 {
|
||||
Object prop;
|
||||
|
||||
constructor(Dir3 dir3) {
|
||||
}
|
||||
}
|
@ -0,0 +1,119 @@
|
||||
import {benchmark, benchmarkStep} from '../benchpress';
|
||||
|
||||
var COUNT = 30;
|
||||
var $compile;
|
||||
var $rootScope;
|
||||
|
||||
export function main() {
|
||||
|
||||
benchmark(`Ng 1.3 Compiler.compile 5*${COUNT} element no bindings`, function() {
|
||||
var template = loadTemplate('templateNoBindings', COUNT);
|
||||
|
||||
benchmarkStep('run', function() {
|
||||
// Need to clone every time as the compiler might modify the template!
|
||||
var cloned = template.cloneNode(true);
|
||||
$compile(cloned);
|
||||
});
|
||||
});
|
||||
|
||||
benchmark(`Ng 1.3 Compiler.compile 5*${COUNT} element with bindings`, function() {
|
||||
var template = loadTemplate('templateWithBindings', COUNT);
|
||||
|
||||
benchmarkStep('run', function() {
|
||||
// Need to clone every time as the compiler might modify the template!
|
||||
var cloned = template.cloneNode(true);
|
||||
$compile(cloned);
|
||||
});
|
||||
});
|
||||
|
||||
benchmark(`Ng 1.3 instantiate 5*${COUNT} element with bindings`, function() {
|
||||
var linkFn;
|
||||
|
||||
setTimeout(function() {
|
||||
var template = loadTemplate('templateWithBindings', COUNT);
|
||||
linkFn = $compile(template);
|
||||
});
|
||||
|
||||
benchmarkStep('run', function() {
|
||||
var scope = $rootScope.$new();
|
||||
linkFn(scope);
|
||||
scope.$destroy();
|
||||
});
|
||||
});
|
||||
|
||||
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', function($parse) {
|
||||
return {
|
||||
compile: function($element, $attrs) {
|
||||
var expr = $parse($attrs.attr0);
|
||||
return function($scope) {
|
||||
$scope.$watch(expr, angular.noop);
|
||||
}
|
||||
}
|
||||
};
|
||||
})
|
||||
.directive('dir1', function($parse) {
|
||||
return {
|
||||
compile: function($element, $attrs) {
|
||||
var expr = $parse($attrs.attr1);
|
||||
return function($scope) {
|
||||
$scope.$watch(expr, angular.noop);
|
||||
}
|
||||
}
|
||||
};
|
||||
})
|
||||
.directive('dir2', function($parse) {
|
||||
return {
|
||||
compile: function($element, $attrs) {
|
||||
var expr = $parse($attrs.attr2);
|
||||
return function($scope) {
|
||||
$scope.$watch(expr, angular.noop);
|
||||
}
|
||||
}
|
||||
};
|
||||
})
|
||||
.directive('dir3', function($parse) {
|
||||
return {
|
||||
compile: function($element, $attrs) {
|
||||
var expr = $parse($attrs.attr3);
|
||||
return function($scope) {
|
||||
$scope.$watch(expr, angular.noop);
|
||||
}
|
||||
}
|
||||
};
|
||||
})
|
||||
.directive('dir4', function($parse) {
|
||||
return {
|
||||
compile: function($element, $attrs) {
|
||||
var expr = $parse($attrs.attr4);
|
||||
return function($scope) {
|
||||
$scope.$watch(expr, angular.noop);
|
||||
}
|
||||
}
|
||||
};
|
||||
})
|
||||
.run(function(_$compile_, _$rootScope_) {
|
||||
$compile = _$compile_;
|
||||
$rootScope = _$rootScope_;
|
||||
});
|
||||
|
30
modules/benchmarks_external/src/compiler/main.html
Normal file
30
modules/benchmarks_external/src/compiler/main.html
Normal file
@ -0,0 +1,30 @@
|
||||
<template id="templateNoBindings">
|
||||
<div class="class0 class1 class2 class3 class4 " nodir0="" attr0="value0" nodir1="" attr1="value1" nodir2="" attr2="value2" nodir3="" attr3="value3" nodir4="" attr4="value4">
|
||||
<div class="class0 class1 class2 class3 class4 " nodir0="" attr0="value0" nodir1="" attr1="value1" nodir2="" attr2="value2" nodir3="" attr3="value3" nodir4="" attr4="value4">
|
||||
<div class="class0 class1 class2 class3 class4 " nodir0="" attr0="value0" nodir1="" attr1="value1" nodir2="" attr2="value2" nodir3="" attr3="value3" nodir4="" attr4="value4">
|
||||
<div class="class0 class1 class2 class3 class4 " nodir0="" attr0="value0" nodir1="" attr1="value1" nodir2="" attr2="value2" nodir3="" attr3="value3" nodir4="" attr4="value4">
|
||||
<div class="class0 class1 class2 class3 class4 " nodir0="" attr0="value0" nodir1="" attr1="value1" nodir2="" attr2="value2" nodir3="" attr3="value3" nodir4="" attr4="value4">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template id="templateWithBindings">
|
||||
<div class="class0 class1 class2 class3 class4 " dir0="" [attr0]="value0" dir1="" [attr1]="value1" dir2="" [attr2]="value2" dir3="" [attr3]="value3" dir4="" [attr4]="value4">
|
||||
{{inter0}}{{inter1}}{{inter2}}{{inter3}}{{inter4}}
|
||||
<div class="class0 class1 class2 class3 class4 " dir0="" [attr0]="value0" dir1="" [attr1]="value1" dir2="" [attr2]="value2" dir3="" [attr3]="value3" dir4="" [attr4]="value4">
|
||||
{{inter0}}{{inter1}}{{inter2}}{{inter3}}{{inter4}}
|
||||
<div class="class0 class1 class2 class3 class4 " dir0="" [attr0]="value0" dir1="" [attr1]="value1" dir2="" [attr2]="value2" dir3="" [attr3]="value3" dir4="" [attr4]="value4">
|
||||
{{inter0}}{{inter1}}{{inter2}}{{inter3}}{{inter4}}
|
||||
<div class="class0 class1 class2 class3 class4 " dir0="" [attr0]="value0" dir1="" [attr1]="value1" dir2="" [attr2]="value2" dir3="" [attr3]="value3" dir4="" [attr4]="value4">
|
||||
{{inter0}}{{inter1}}{{inter2}}{{inter3}}{{inter4}}
|
||||
<div class="class0 class1 class2 class3 class4 " dir0="" [attr0]="value0" dir1="" [attr1]="value1" dir2="" [attr2]="value2" dir3="" [attr3]="value3" dir4="" [attr4]="value4">
|
||||
{{inter0}}{{inter1}}{{inter2}}{{inter3}}{{inter4}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
11
modules/benchmarks_external/src/compiler/register_system.es5
Normal file
11
modules/benchmarks_external/src/compiler/register_system.es5
Normal file
@ -0,0 +1,11 @@
|
||||
System.paths = {
|
||||
'core/*': '/js/core/lib/*.js',
|
||||
'change_detection/*': '/js/change_detection/lib/*.js',
|
||||
'facade/*': '/js/facade/lib/*.js',
|
||||
'di/*': '/js/di/lib/*.js',
|
||||
'rtts_assert/*': '/js/rtts_assert/lib/*.js',
|
||||
'test_lib/*': '/js/test_lib/lib/*.js',
|
||||
'benchmarks_external/*': '/js/benchmarks_external/lib/*.js',
|
||||
'reflection/*': '/js/reflection/lib/*.js'
|
||||
};
|
||||
register(System);
|
Reference in New Issue
Block a user