refactor(benchmark): simplify writing benchmarks
Adds `benchmarks/benchpress` module and adjusts the compiler benchmarks to use it. Also adds the Angular 1.3 benchmark to the compiler benchmarks. Closes #202
This commit is contained in:
parent
be4cb2db3a
commit
8dfbc242af
63
modules/benchmarks/src/benchpress.dart
Normal file
63
modules/benchmarks/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/src/benchpress.es6
Normal file
55
modules/benchmarks/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
|
||||||
|
});
|
||||||
|
}
|
@ -2,35 +2,8 @@ library compiler_benchmark;
|
|||||||
|
|
||||||
import './selector_benchmark.dart' as sbm;
|
import './selector_benchmark.dart' as sbm;
|
||||||
import './compiler_benchmark.dart' as cbm;
|
import './compiler_benchmark.dart' as cbm;
|
||||||
import 'dart:js' as js;
|
|
||||||
|
|
||||||
main () {
|
main () {
|
||||||
sbm.setup();
|
sbm.main();
|
||||||
cbm.setup();
|
cbm.main();
|
||||||
|
|
||||||
js.context['benchmarkSteps'].add(new js.JsObject.jsify({
|
|
||||||
"name": "CssSelector.parse * 1000",
|
|
||||||
"fn": new js.JsFunction.withThis((_) => sbm.runParse())
|
|
||||||
}));
|
|
||||||
js.context['benchmarkSteps'].add(new js.JsObject.jsify({
|
|
||||||
"name": "SelectorMatcher.addSelectable * 1000",
|
|
||||||
"fn": new js.JsFunction.withThis((_) => sbm.runAdd())
|
|
||||||
}));
|
|
||||||
js.context['benchmarkSteps'].add(new js.JsObject.jsify({
|
|
||||||
"name": "SelectorMatcher.match * 1000",
|
|
||||||
"fn": new js.JsFunction.withThis((_) => sbm.runMatch())
|
|
||||||
}));
|
|
||||||
|
|
||||||
js.context['benchmarkSteps'].add(new js.JsObject.jsify({
|
|
||||||
"name": "Compiler.compile empty template",
|
|
||||||
"fn": new js.JsFunction.withThis((_) => cbm.compileEmptyTemplate())
|
|
||||||
}));
|
|
||||||
js.context['benchmarkSteps'].add(new js.JsObject.jsify({
|
|
||||||
"name": "Compiler.compile 25 element no bindings",
|
|
||||||
"fn": new js.JsFunction.withThis((_) => cbm.compile25ElementsNoBindings())
|
|
||||||
}));
|
|
||||||
js.context['benchmarkSteps'].add(new js.JsObject.jsify({
|
|
||||||
"name": "Compiler.compile 25 element with bindings",
|
|
||||||
"fn": new js.JsFunction.withThis((_) => cbm.compile25ElementsWithBindings())
|
|
||||||
}));
|
|
||||||
}
|
}
|
@ -1,35 +1,9 @@
|
|||||||
System.import('benchmarks/compiler/selector_benchmark').then(function (bm) {
|
Promise.all([
|
||||||
bm.setup();
|
System.import('benchmarks/compiler/selector_benchmark'),
|
||||||
|
System.import('benchmarks/compiler/compiler_benchmark'),
|
||||||
window.benchmarkSteps.push({name: 'CssSelector.parse * 1000', fn: bm.runParse});
|
System.import('benchmarks/compiler/compiler_benchmark_ng13')
|
||||||
}, console.log.bind(console));
|
]).then(function (benchmarks) {
|
||||||
|
benchmarks.forEach(function(bm) {
|
||||||
System.import('benchmarks/compiler/selector_benchmark').then(function (bm) {
|
bm.main();
|
||||||
bm.setup();
|
});
|
||||||
|
|
||||||
window.benchmarkSteps.push({name: 'SelectorMatcher.addSelectable * 1000', fn: bm.runAdd});
|
|
||||||
}, console.log.bind(console));
|
|
||||||
|
|
||||||
System.import('benchmarks/compiler/selector_benchmark').then(function (bm) {
|
|
||||||
bm.setup();
|
|
||||||
|
|
||||||
window.benchmarkSteps.push({name: 'SelectorMatcher.match * 1000', fn: bm.runMatch});
|
|
||||||
}, console.log.bind(console));
|
|
||||||
|
|
||||||
System.import('benchmarks/compiler/compiler_benchmark').then(function (bm) {
|
|
||||||
bm.setup();
|
|
||||||
|
|
||||||
window.benchmarkSteps.push({name: 'Compiler.compile empty template', fn: bm.compileEmptyTemplate});
|
|
||||||
}, console.log.bind(console));
|
|
||||||
|
|
||||||
System.import('benchmarks/compiler/compiler_benchmark').then(function (bm) {
|
|
||||||
bm.setup();
|
|
||||||
|
|
||||||
window.benchmarkSteps.push({name: 'Compiler.compile 25 element no bindings', fn: bm.compile25ElementsNoBindings});
|
|
||||||
}, console.log.bind(console));
|
|
||||||
|
|
||||||
System.import('benchmarks/compiler/compiler_benchmark').then(function (bm) {
|
|
||||||
bm.setup();
|
|
||||||
|
|
||||||
window.benchmarkSteps.push({name: 'Compiler.compile 25 element with bindings', fn: bm.compile25ElementsWithBindings});
|
|
||||||
}, console.log.bind(console));
|
}, console.log.bind(console));
|
||||||
|
@ -4,7 +4,8 @@ module.exports = function(config) {
|
|||||||
{src: '/js/traceur-runtime.js'},
|
{src: '/js/traceur-runtime.js'},
|
||||||
{src: '/js/es6-module-loader-sans-promises.src.js'},
|
{src: '/js/es6-module-loader-sans-promises.src.js'},
|
||||||
{src: '/js/extension-register.js'},
|
{src: '/js/extension-register.js'},
|
||||||
{src: 'register_system.js'},
|
{src: 'paths.js'},
|
||||||
|
{src: 'https://ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.js'},
|
||||||
{src: 'benchmark.js'}
|
{src: 'benchmark.js'}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
import {DOM} from 'facade/dom';
|
import {benchmark, benchmarkStep} from '../benchpress';
|
||||||
|
|
||||||
|
import {DOM, document} from 'facade/dom';
|
||||||
|
import {isBlank} from 'facade/lang';
|
||||||
|
import {MapWrapper} from 'facade/collection';
|
||||||
|
import {AnnotatedType} from 'core/compiler/annotated_type';
|
||||||
|
|
||||||
import {Parser} from 'change_detection/parser/parser';
|
import {Parser} from 'change_detection/parser/parser';
|
||||||
import {ClosureMap} from 'change_detection/parser/closure_map';
|
import {ClosureMap} from 'change_detection/parser/closure_map';
|
||||||
@ -11,39 +16,65 @@ import {Component} from 'core/annotations/component';
|
|||||||
import {Decorator} from 'core/annotations/decorator';
|
import {Decorator} from 'core/annotations/decorator';
|
||||||
import {TemplateConfig} from 'core/annotations/template_config';
|
import {TemplateConfig} from 'core/annotations/template_config';
|
||||||
|
|
||||||
|
var COUNT = 30;
|
||||||
|
|
||||||
var compiler;
|
var compiler;
|
||||||
var annotatedComponent;
|
var annotatedComponent;
|
||||||
var annotatedComponentNoDirectives;
|
|
||||||
|
|
||||||
var emptyTemplate;
|
function setup() {
|
||||||
var templateWith25ElementsNoBindings;
|
|
||||||
var templateWith25ElementsAndBindings;
|
|
||||||
|
|
||||||
export function setup() {
|
|
||||||
var closureMap = new ClosureMap();
|
var closureMap = new ClosureMap();
|
||||||
var reflector = new Reflector();
|
var reflector = new CachingReflector();
|
||||||
compiler = new Compiler(null, reflector, new Parser(new Lexer(), closureMap), closureMap);
|
compiler = new Compiler(null, reflector, new Parser(new Lexer(), closureMap), closureMap);
|
||||||
annotatedComponent = reflector.annotatedType(SomeComponent);
|
annotatedComponent = reflector.annotatedType(BenchmarkComponent);
|
||||||
annotatedComponentNoDirectives = reflector.annotatedType(ComponentWithNoDirectives);
|
|
||||||
|
|
||||||
emptyTemplate = createTemplate('<div></div>');
|
|
||||||
templateWith25ElementsNoBindings = buildTemplateWith25ElementsNoBindings();
|
|
||||||
templateWith25ElementsAndBindings = buildTemplateWith25ElementsAndBindings();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function compileEmptyTemplate() {
|
export function main() {
|
||||||
var template = emptyTemplate;
|
setup();
|
||||||
return compiler.compileWithCache(null, annotatedComponent, template);
|
|
||||||
|
benchmark(`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 = DOM.clone(template);
|
||||||
|
compiler.compileWithCache(null, annotatedComponent, cloned);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
benchmark(`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 = DOM.clone(template);
|
||||||
|
compiler.compileWithCache(null, annotatedComponent, cloned);
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function compile25ElementsWithBindings() {
|
function loadTemplate(templateId, repeatCount) {
|
||||||
var template = templateWith25ElementsAndBindings;
|
var template = DOM.querySelectorAll(document, `#${templateId}`)[0];
|
||||||
return compiler.compileWithCache(null, annotatedComponent, template);
|
var content = DOM.getInnerHTML(template);
|
||||||
|
var result = '';
|
||||||
|
for (var i=0; i<repeatCount; i++) {
|
||||||
|
result += content;
|
||||||
|
}
|
||||||
|
return DOM.createTemplate(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function compile25ElementsNoBindings() {
|
// Caching reflector as reflection in Dart using Mirrors
|
||||||
var template = templateWith25ElementsNoBindings;
|
class CachingReflector extends Reflector {
|
||||||
return compiler.compileWithCache(null, annotatedComponentNoDirectives, template);
|
constructor() {
|
||||||
|
this._cache = MapWrapper.create();
|
||||||
|
}
|
||||||
|
annotatedType(type:Type):AnnotatedType {
|
||||||
|
var result = MapWrapper.get(this._cache, type);
|
||||||
|
if (isBlank(result)) {
|
||||||
|
result = super.annotatedType(type);
|
||||||
|
MapWrapper.set(this._cache, type, result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Decorator({
|
@Decorator({
|
||||||
@ -91,79 +122,5 @@ class Dir4 {}
|
|||||||
directives: [Dir0, Dir1, Dir2, Dir3, Dir4]
|
directives: [Dir0, Dir1, Dir2, Dir3, Dir4]
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
class SomeComponent {}
|
class BenchmarkComponent {}
|
||||||
|
|
||||||
@Component({
|
|
||||||
template: new TemplateConfig({
|
|
||||||
directives: []
|
|
||||||
})
|
|
||||||
})
|
|
||||||
class ComponentWithNoDirectives {}
|
|
||||||
|
|
||||||
// creates 25 nested divs without bindings, each looking like this:
|
|
||||||
// <div class="class0 class1 class2 class3 class4 " dir0="" attr0="value0" dir1="" attr1="value1" dir2="" attr2="value2" dir3="" attr3="value3" dir4="" attr4="value4">
|
|
||||||
// </div>
|
|
||||||
function buildTemplateWith25ElementsNoBindings() {
|
|
||||||
var result = '';
|
|
||||||
for (var i=0; i<5; i++) {
|
|
||||||
for (var j=0; j<5; j++) {
|
|
||||||
result += '<div class="';
|
|
||||||
for (var k=0; k<5; k++) {
|
|
||||||
result += `class${k} `;
|
|
||||||
}
|
|
||||||
result += '"';
|
|
||||||
for (var k=0; k<5; k++) {
|
|
||||||
result += ` dir${k}`;
|
|
||||||
result += ` attr${k}=value${k}`;
|
|
||||||
}
|
|
||||||
for (var k=0; k<5; k++) {
|
|
||||||
result += ` dir${k}`;
|
|
||||||
result += ` attr${k}=value${k}`;
|
|
||||||
}
|
|
||||||
result += '>';
|
|
||||||
}
|
|
||||||
for (var j=0; j<5; j++) {
|
|
||||||
result += '</div>';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return createTemplate(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// creates 25 nested divs , each looking like this:
|
|
||||||
// <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>
|
|
||||||
function buildTemplateWith25ElementsAndBindings() {
|
|
||||||
var result = '';
|
|
||||||
for (var i=0; i<5; i++) {
|
|
||||||
for (var j=0; j<5; j++) {
|
|
||||||
result += '<div class="';
|
|
||||||
for (var k=0; k<5; k++) {
|
|
||||||
result += `class${k} `;
|
|
||||||
}
|
|
||||||
result += '"';
|
|
||||||
for (var k=0; k<5; k++) {
|
|
||||||
result += ` dir${k}`;
|
|
||||||
result += ` [attr${k}]=value${k}`;
|
|
||||||
}
|
|
||||||
for (var k=0; k<5; k++) {
|
|
||||||
result += ` dir${k}`;
|
|
||||||
result += ` [attr${k}]=value${k}`;
|
|
||||||
}
|
|
||||||
result += '>';
|
|
||||||
for (var k=0; k<5; k++) {
|
|
||||||
result += `{{inter${k}}}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (var j=0; j<5; j++) {
|
|
||||||
result += '</div>';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return createTemplate(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function createTemplate(html) {
|
|
||||||
return DOM.createTemplate(html);
|
|
||||||
}
|
|
||||||
|
102
modules/benchmarks/src/compiler/compiler_benchmark_ng13.es6
Normal file
102
modules/benchmarks/src/compiler/compiler_benchmark_ng13.es6
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
import {benchmark, benchmarkStep} from '../benchpress';
|
||||||
|
|
||||||
|
var COUNT = 30;
|
||||||
|
var $compile;
|
||||||
|
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
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_) {
|
||||||
|
$compile = _$compile_;
|
||||||
|
});
|
||||||
|
|
@ -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>
|
@ -1,3 +1,5 @@
|
|||||||
|
import {benchmark, benchmarkStep} from '../benchpress';
|
||||||
|
|
||||||
import {SelectorMatcher} from "core/compiler/selector";
|
import {SelectorMatcher} from "core/compiler/selector";
|
||||||
import {CssSelector} from "core/compiler/selector";
|
import {CssSelector} from "core/compiler/selector";
|
||||||
import {StringWrapper, Math} from 'facade/lang';
|
import {StringWrapper, Math} from 'facade/lang';
|
||||||
@ -9,46 +11,55 @@ var fixedSelectors = [];
|
|||||||
|
|
||||||
var COUNT = 1000;
|
var COUNT = 1000;
|
||||||
|
|
||||||
export function setup() {
|
export function main() {
|
||||||
for (var i=0; i<COUNT; i++) {
|
setup(COUNT);
|
||||||
|
|
||||||
|
benchmark(`cssSelector.parse * ${COUNT}`, function() {
|
||||||
|
benchmarkStep(`run`, function() {
|
||||||
|
var result = [];
|
||||||
|
for (var i=0; i<COUNT; i++) {
|
||||||
|
ListWrapper.push(result, CssSelector.parse(fixedSelectorStrings[i]));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
benchmark(`cssSelector.addSelectable * ${COUNT}`, function() {
|
||||||
|
benchmarkStep(`run`, function() {
|
||||||
|
var matcher = new SelectorMatcher();
|
||||||
|
for (var i=0; i<COUNT; i++) {
|
||||||
|
matcher.addSelectable(fixedSelectors[i], i);
|
||||||
|
}
|
||||||
|
return matcher;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
benchmark(`cssSelector.match * ${COUNT}`, function() {
|
||||||
|
benchmarkStep(`run`, function() {
|
||||||
|
var matchCount = 0;
|
||||||
|
for (var i=0; i<COUNT; i++) {
|
||||||
|
fixedMatcher.match(fixedSelectors[i], (selected) => {
|
||||||
|
matchCount += selected;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return matchCount;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function setup(count) {
|
||||||
|
for (var i=0; i<count; i++) {
|
||||||
ListWrapper.push(fixedSelectorStrings, randomSelector());
|
ListWrapper.push(fixedSelectorStrings, randomSelector());
|
||||||
}
|
}
|
||||||
for (var i=0; i<COUNT; i++) {
|
for (var i=0; i<count; i++) {
|
||||||
ListWrapper.push(fixedSelectors, CssSelector.parse(fixedSelectorStrings[i]));
|
ListWrapper.push(fixedSelectors, CssSelector.parse(fixedSelectorStrings[i]));
|
||||||
}
|
}
|
||||||
fixedMatcher = new SelectorMatcher();
|
fixedMatcher = new SelectorMatcher();
|
||||||
for (var i=0; i<COUNT; i++) {
|
for (var i=0; i<count; i++) {
|
||||||
fixedMatcher.addSelectable(fixedSelectors[i], i);
|
fixedMatcher.addSelectable(fixedSelectors[i], i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function runParse() {
|
|
||||||
var result = [];
|
|
||||||
for (var i=0; i<COUNT; i++) {
|
|
||||||
ListWrapper.push(result, CssSelector.parse(fixedSelectorStrings[i]));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function runAdd() {
|
|
||||||
var matcher = new SelectorMatcher();
|
|
||||||
for (var i=0; i<COUNT; i++) {
|
|
||||||
matcher.addSelectable(fixedSelectors[i], i);
|
|
||||||
}
|
|
||||||
return matcher;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function runMatch() {
|
|
||||||
// The sum is used to prevent Chrome from optimizing the loop away...
|
|
||||||
var count = 0;
|
|
||||||
for (var i=0; i<COUNT; i++) {
|
|
||||||
fixedMatcher.match(fixedSelectors[i], (selected) => {
|
|
||||||
count += selected;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
function randomSelector() {
|
function randomSelector() {
|
||||||
var res = randomStr(5);
|
var res = randomStr(5);
|
||||||
for (var i=0; i<3; i++) {
|
for (var i=0; i<3; i++) {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
library change_detection.parser.closure_map;
|
||||||
|
|
||||||
import 'dart:mirrors';
|
import 'dart:mirrors';
|
||||||
|
|
||||||
typedef SetterFn(Object obj, value);
|
typedef SetterFn(Object obj, value);
|
||||||
|
@ -3,7 +3,7 @@ library angular.core.facade.dom;
|
|||||||
import 'dart:html';
|
import 'dart:html';
|
||||||
import 'dart:js' show JsObject;
|
import 'dart:js' show JsObject;
|
||||||
|
|
||||||
export 'dart:html' show DocumentFragment, Node, Element, TemplateElement, Text;
|
export 'dart:html' show DocumentFragment, Node, Element, TemplateElement, Text, document, location;
|
||||||
|
|
||||||
// TODO(tbosch): Is there a builtin one? Why is Dart
|
// TODO(tbosch): Is there a builtin one? Why is Dart
|
||||||
// removing unknown elements by default?
|
// removing unknown elements by default?
|
||||||
|
@ -4,6 +4,9 @@ export var NodeList = window.NodeList;
|
|||||||
export var Text = window.Text;
|
export var Text = window.Text;
|
||||||
export var Element = window.HTMLElement;
|
export var Element = window.HTMLElement;
|
||||||
export var TemplateElement = window.HTMLTemplateElement;
|
export var TemplateElement = window.HTMLTemplateElement;
|
||||||
|
export var document = window.document;
|
||||||
|
export var location = window.location;
|
||||||
|
|
||||||
import {List, MapWrapper} from 'facade/collection';
|
import {List, MapWrapper} from 'facade/collection';
|
||||||
|
|
||||||
export class DOM {
|
export class DOM {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user