feat(compiler): add benchmarks
- compileEmptyTemplate - compile25ElementsNoBindings - compile25ElementsWithBindings For the results see the PR #197. Closes #197
This commit is contained in:
parent
aa9eeb80e7
commit
b07ea6b90e
|
@ -0,0 +1,36 @@
|
||||||
|
library compiler_benchmark;
|
||||||
|
|
||||||
|
import './selector_benchmark.dart' as sbm;
|
||||||
|
import './compiler_benchmark.dart' as cbm;
|
||||||
|
import 'dart:js' as js;
|
||||||
|
|
||||||
|
main () {
|
||||||
|
sbm.setup();
|
||||||
|
cbm.setup();
|
||||||
|
|
||||||
|
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,17 +1,35 @@
|
||||||
System.import('benchmarks/compiler/selector_benchmark').then(function (bm) {
|
System.import('benchmarks/compiler/selector_benchmark').then(function (bm) {
|
||||||
bm.setup();
|
bm.setup();
|
||||||
|
|
||||||
window.benchmarkSteps.push({name: 'CssSelector.parse', fn: bm.runParse});
|
window.benchmarkSteps.push({name: 'CssSelector.parse * 1000', fn: bm.runParse});
|
||||||
}, console.log.bind(console));
|
}, console.log.bind(console));
|
||||||
|
|
||||||
System.import('benchmarks/compiler/selector_benchmark').then(function (bm) {
|
System.import('benchmarks/compiler/selector_benchmark').then(function (bm) {
|
||||||
bm.setup();
|
bm.setup();
|
||||||
|
|
||||||
window.benchmarkSteps.push({name: 'SelectorMatcher.addSelectable', fn: bm.runAdd});
|
window.benchmarkSteps.push({name: 'SelectorMatcher.addSelectable * 1000', fn: bm.runAdd});
|
||||||
}, console.log.bind(console));
|
}, console.log.bind(console));
|
||||||
|
|
||||||
System.import('benchmarks/compiler/selector_benchmark').then(function (bm) {
|
System.import('benchmarks/compiler/selector_benchmark').then(function (bm) {
|
||||||
bm.setup();
|
bm.setup();
|
||||||
|
|
||||||
window.benchmarkSteps.push({name: 'SelectorMatcher.match', fn: bm.runMatch});
|
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));
|
||||||
|
|
|
@ -0,0 +1,169 @@
|
||||||
|
import {DOM} from 'facade/dom';
|
||||||
|
|
||||||
|
import {Parser} from 'change_detection/parser/parser';
|
||||||
|
import {ClosureMap} from 'change_detection/parser/closure_map';
|
||||||
|
import {Lexer} from 'change_detection/parser/lexer';
|
||||||
|
|
||||||
|
import {Compiler} from 'core/compiler/compiler';
|
||||||
|
import {Reflector} from 'core/compiler/reflector';
|
||||||
|
|
||||||
|
import {Component} from 'core/annotations/component';
|
||||||
|
import {Decorator} from 'core/annotations/decorator';
|
||||||
|
import {TemplateConfig} from 'core/annotations/template_config';
|
||||||
|
|
||||||
|
var compiler;
|
||||||
|
var annotatedComponent;
|
||||||
|
var annotatedComponentNoDirectives;
|
||||||
|
|
||||||
|
var emptyTemplate;
|
||||||
|
var templateWith25ElementsNoBindings;
|
||||||
|
var templateWith25ElementsAndBindings;
|
||||||
|
|
||||||
|
export function setup() {
|
||||||
|
var closureMap = new ClosureMap();
|
||||||
|
var reflector = new Reflector();
|
||||||
|
compiler = new Compiler(null, reflector, new Parser(new Lexer(), closureMap), closureMap);
|
||||||
|
annotatedComponent = reflector.annotatedType(SomeComponent);
|
||||||
|
annotatedComponentNoDirectives = reflector.annotatedType(ComponentWithNoDirectives);
|
||||||
|
|
||||||
|
emptyTemplate = createTemplate('<div></div>');
|
||||||
|
templateWith25ElementsNoBindings = buildTemplateWith25ElementsNoBindings();
|
||||||
|
templateWith25ElementsAndBindings = buildTemplateWith25ElementsAndBindings();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function compileEmptyTemplate() {
|
||||||
|
var template = emptyTemplate;
|
||||||
|
return compiler.compileWithCache(null, annotatedComponent, template);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function compile25ElementsWithBindings() {
|
||||||
|
var template = templateWith25ElementsAndBindings;
|
||||||
|
return compiler.compileWithCache(null, annotatedComponent, template);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function compile25ElementsNoBindings() {
|
||||||
|
var template = templateWith25ElementsNoBindings;
|
||||||
|
return compiler.compileWithCache(null, annotatedComponentNoDirectives, template);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Decorator({
|
||||||
|
selector: '[dir0]',
|
||||||
|
bind: {
|
||||||
|
'attr0': 'prop'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
class Dir0 {}
|
||||||
|
|
||||||
|
@Decorator({
|
||||||
|
selector: '[dir1]',
|
||||||
|
bind: {
|
||||||
|
'attr1': 'prop'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
class Dir1 {}
|
||||||
|
|
||||||
|
@Decorator({
|
||||||
|
selector: '[dir2]',
|
||||||
|
bind: {
|
||||||
|
'attr2': 'prop'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
class Dir2 {}
|
||||||
|
|
||||||
|
@Decorator({
|
||||||
|
selector: '[dir3]',
|
||||||
|
bind: {
|
||||||
|
'attr3': 'prop'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
class Dir3 {}
|
||||||
|
|
||||||
|
@Decorator({
|
||||||
|
selector: '[dir4]',
|
||||||
|
bind: {
|
||||||
|
'attr4': 'prop'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
class Dir4 {}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
template: new TemplateConfig({
|
||||||
|
directives: [Dir0, Dir1, Dir2, Dir3, Dir4]
|
||||||
|
})
|
||||||
|
})
|
||||||
|
class SomeComponent {}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
}
|
|
@ -31,13 +31,11 @@ export function runParse() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function runAdd() {
|
export function runAdd() {
|
||||||
// The sum is used to prevent Chrome from optimizing the loop away...
|
|
||||||
var matcher = new SelectorMatcher();
|
var matcher = new SelectorMatcher();
|
||||||
var count = 0;
|
|
||||||
for (var i=0; i<COUNT; i++) {
|
for (var i=0; i<COUNT; i++) {
|
||||||
count += matcher.addSelectable(fixedSelectors[i], i);
|
matcher.addSelectable(fixedSelectors[i], i);
|
||||||
}
|
}
|
||||||
return count;
|
return matcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function runMatch() {
|
export function runMatch() {
|
||||||
|
@ -72,7 +70,7 @@ function randomStr(len){
|
||||||
|
|
||||||
function randomChar(){
|
function randomChar(){
|
||||||
var n = randomNum(62);
|
var n = randomNum(62);
|
||||||
if(n<10) return n; //1-10
|
if(n<10) return n.toString(); //1-10
|
||||||
if(n<36) return StringWrapper.fromCharCode(n+55); //A-Z
|
if(n<36) return StringWrapper.fromCharCode(n+55); //A-Z
|
||||||
return StringWrapper.fromCharCode(n+61); //a-z
|
return StringWrapper.fromCharCode(n+61); //a-z
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,14 +39,13 @@ export class Compiler {
|
||||||
compile(component:Type, templateRoot:Element = null):Promise<ProtoView> {
|
compile(component:Type, templateRoot:Element = null):Promise<ProtoView> {
|
||||||
// TODO load all components transitively from the cache first
|
// TODO load all components transitively from the cache first
|
||||||
var cache = null;
|
var cache = null;
|
||||||
return PromiseWrapper.resolve(this._compileAllCached(
|
return PromiseWrapper.resolve(this.compileWithCache(
|
||||||
this._reflector.annotatedType(component),
|
cache, this._reflector.annotatedType(component), templateRoot)
|
||||||
cache,
|
|
||||||
templateRoot)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_compileAllCached(component:AnnotatedType, cache, templateRoot:Element = null):ProtoView {
|
// public so that we can compile in sync in performance tests.
|
||||||
|
compileWithCache(cache, component:AnnotatedType, templateRoot:Element = null):ProtoView {
|
||||||
if (isBlank(templateRoot)) {
|
if (isBlank(templateRoot)) {
|
||||||
// TODO: read out the cache if templateRoot = null. Could contain:
|
// TODO: read out the cache if templateRoot = null. Could contain:
|
||||||
// - templateRoot string
|
// - templateRoot string
|
||||||
|
@ -62,7 +61,7 @@ export class Compiler {
|
||||||
for (var i=0; i<compileElements.length; i++) {
|
for (var i=0; i<compileElements.length; i++) {
|
||||||
var ce = compileElements[i];
|
var ce = compileElements[i];
|
||||||
if (isPresent(ce.componentDirective)) {
|
if (isPresent(ce.componentDirective)) {
|
||||||
ce.inheritedElementBinder.nestedProtoView = this._compileAllCached(ce.componentDirective, cache, null);
|
ce.inheritedElementBinder.nestedProtoView = this.compileWithCache(cache, ce.componentDirective, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library facade.di.reflector;
|
library facade.compiler.reflector;
|
||||||
|
|
||||||
import 'dart:mirrors';
|
import 'dart:mirrors';
|
||||||
import '../annotations/directive.dart';
|
import '../annotations/directive.dart';
|
||||||
|
|
Loading…
Reference in New Issue