refactor(compiler_benchmark): simplify by using bootstrap and DI

Closes #4356
This commit is contained in:
Tobias Bosch 2015-09-24 14:51:19 -07:00
parent 0a88e7b736
commit 5f640c79bb
3 changed files with 92 additions and 84 deletions

View File

@ -7,6 +7,7 @@ describe('ng2 compiler benchmark', function() {
afterEach(verifyNoBrowserErrors);
it('should log withBindings stats', function(done) {
browser.sleep(1000);
runBenchmark({
url: URL,
id: 'ng2.compile.withBindings',
@ -19,6 +20,7 @@ describe('ng2 compiler benchmark', function() {
});
it('should log noBindings stats', function(done) {
browser.sleep(1000);
runBenchmark({
url: URL,
id: 'ng2.compile.noBindings',

View File

@ -5,7 +5,7 @@
<h2>Params</h2>
<form>
Elements:
<input type="number" name="elements" placeholder="elements" value="150">
<input type="number" name="elements" placeholder="elements" value="50">
<br>
<button>Apply</button>
</form>
@ -15,6 +15,8 @@
<button id="compileWithBindings">CompileWithBindings</button>
<button id="compileNoBindings">CompileNoBindings</button>
</p>
<app></app>
$SCRIPTS$
</body>

View File

@ -1,82 +1,112 @@
import {bootstrap} from 'angular2/bootstrap';
import {BrowserDomAdapter} from 'angular2/src/core/dom/browser_adapter';
import {DOM} from 'angular2/src/core/dom/dom_adapter';
import {PromiseWrapper} from 'angular2/src/core/facade/async';
import {ListWrapper, Map, MapWrapper} from 'angular2/src/core/facade/collection';
import {DateWrapper, Type, print} from 'angular2/src/core/facade/lang';
import {DateWrapper, Type, print, isPresent} from 'angular2/src/core/facade/lang';
import {
Parser,
Lexer,
Compiler,
Component,
Directive,
View,
ViewContainerRef,
bind,
Binding,
NgIf,
ViewMetadata
} from 'angular2/core';
import {CompilerCache} from 'angular2/src/core/compiler/compiler';
import {
ChangeDetection,
DynamicChangeDetection
} from 'angular2/src/core/change_detection/change_detection';
import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
import {DirectiveResolver} from 'angular2/src/core/compiler/directive_resolver';
import {PipeResolver} from 'angular2/src/core/compiler/pipe_resolver';
import {Component, Directive, View, ViewMetadata} from 'angular2/src/core/metadata';
import {ViewResolver} from 'angular2/src/core/compiler/view_resolver';
import {UrlResolver} from 'angular2/src/core/services/url_resolver';
import {AppRootUrl} from 'angular2/src/core/services/app_root_url';
import {ComponentUrlMapper} from 'angular2/src/core/compiler/component_url_mapper';
import {reflector} from 'angular2/src/core/reflection/reflection';
import {ReflectionCapabilities} from 'angular2/src/core/reflection/reflection_capabilities';
import {getIntParameter, bindAction} from 'angular2/src/test_lib/benchmark_util';
import {ProtoViewFactory} from 'angular2/src/core/compiler/proto_view_factory';
import {
ViewLoader,
DefaultDomCompiler,
SharedStylesHost,
TemplateCloner
} from 'angular2/src/core/render/render';
import {
DomElementSchemaRegistry
} from 'angular2/src/core/render/dom/schema/dom_element_schema_registry';
function _createBindings(): Binding[] {
var multiplyTemplatesBy = getIntParameter('elements');
return [
bind(ViewResolver)
.toFactory(() => new MultiplyViewResolver(
multiplyTemplatesBy,
[BenchmarkComponentNoBindings, BenchmarkComponentWithBindings]),
[]),
// Use DynamicChangeDetector as that is the only one that Dart supports as well
// so that we can compare the numbers between JS and Dart
bind(ChangeDetection).toClass(DynamicChangeDetection)
];
}
export function main() {
BrowserDomAdapter.makeCurrent();
var count = getIntParameter('elements');
bootstrap(CompilerAppComponent, _createBindings())
.then((ref) => {
var app = ref.hostComponent;
bindAction('#compileNoBindings',
measureWrapper(() => app.compileNoBindings(), 'No Bindings'));
bindAction('#compileWithBindings',
measureWrapper(() => app.compileWithBindings(), 'With Bindings'));
});
}
reflector.reflectionCapabilities = new ReflectionCapabilities();
var reader = new DirectiveResolver();
var pipeResolver = new PipeResolver();
var cache = new CompilerCache();
var viewResolver = new MultipleViewResolver(
count, [BenchmarkComponentNoBindings, BenchmarkComponentWithBindings]);
var urlResolver = new UrlResolver();
var appRootUrl = new AppRootUrl("");
var renderCompiler = new DefaultDomCompiler(
new DomElementSchemaRegistry(), new TemplateCloner(-1), new Parser(new Lexer()),
new ViewLoader(null, null, null), new SharedStylesHost(), 'a');
var compiler = new Compiler(reader, pipeResolver, [], cache, viewResolver,
new ComponentUrlMapper(), urlResolver, renderCompiler,
new ProtoViewFactory(new DynamicChangeDetection()), appRootUrl);
function measureWrapper(func, desc) {
return function() {
var begin = DateWrapper.now();
print(`[${desc}] Begin...`);
var onSuccess = function(_) {
var elapsedMs = DateWrapper.toMillis(DateWrapper.now()) - DateWrapper.toMillis(begin);
print(`[${desc}] ...done, took ${elapsedMs} ms`);
};
PromiseWrapper.then(func(), onSuccess, null);
function measureWrapper(func, desc) {
return function() {
var begin = DateWrapper.now();
print(`[${desc}] Begin...`);
var onSuccess = function(_) {
var elapsedMs = DateWrapper.toMillis(DateWrapper.now()) - DateWrapper.toMillis(begin);
print(`[${desc}] ...done, took ${elapsedMs} ms`);
};
var onError = function(e) { DOM.logError(e); };
PromiseWrapper.then(func(), onSuccess, onError);
};
}
class MultiplyViewResolver extends ViewResolver {
_multiplyBy: number;
_cache: Map<Type, ViewMetadata>;
constructor(multiple: number, components: Type[]) {
super();
this._multiplyBy = multiple;
this._cache = new Map();
ListWrapper.forEach(components, (c) => this._fillCache(c));
}
function compileNoBindings() {
cache.clear();
return compiler.compileInHost(BenchmarkComponentNoBindings);
_fillCache(component: Type) {
var view = super.resolve(component);
var multipliedTemplates = ListWrapper.createFixedSize(this._multiplyBy);
for (var i = 0; i < this._multiplyBy; ++i) {
multipliedTemplates[i] = view.template;
}
this._cache.set(
component,
new ViewMetadata({template: multipliedTemplates.join(''), directives: view.directives}));
}
function compileWithBindings() {
cache.clear();
return compiler.compileInHost(BenchmarkComponentWithBindings);
resolve(component: Type): ViewMetadata {
var result = this._cache.get(component);
return isPresent(result) ? result : super.resolve(component);
}
}
@Component({selector: 'app'})
@View({directives: [], template: ``})
class CompilerAppComponent {
constructor(private _compiler: Compiler, private _compilerCache: CompilerCache) {}
compileNoBindings() {
this._compilerCache.clear();
return this._compiler.compileInHost(BenchmarkComponentNoBindings);
}
bindAction('#compileNoBindings', measureWrapper(compileNoBindings, 'No Bindings'));
bindAction('#compileWithBindings', measureWrapper(compileWithBindings, 'With Bindings'));
compileWithBindings() {
this._compilerCache.clear();
return this._compiler.compileInHost(BenchmarkComponentWithBindings);
}
}
@Directive({selector: '[dir0]', properties: ['prop: attr0']})
@ -103,32 +133,6 @@ class Dir4 {
constructor(dir3: Dir3) {}
}
class MultipleViewResolver extends ViewResolver {
_multiple: number;
_cache: Map<any, any>;
constructor(multiple: number, components: Type[]) {
super();
this._multiple = multiple;
this._cache = new Map();
ListWrapper.forEach(components, (c) => this._warmUp(c));
}
_warmUp(component: Type) {
var view = super.resolve(component);
var multiplier = ListWrapper.createFixedSize(this._multiple);
for (var i = 0; i < this._multiple; ++i) {
multiplier[i] = view.template;
}
this._cache.set(component, ListWrapper.join(multiplier, ''));
}
resolve(component: Type): ViewMetadata {
var view = super.resolve(component);
return new ViewMetadata(
{template:<string>this._cache.get(component), directives: view.directives});
}
}
@Component({selector: 'cmp-nobind'})
@View({