refactor(compiler_benchmark): simplify by using bootstrap and DI
Closes #4356
This commit is contained in:
parent
0a88e7b736
commit
5f640c79bb
|
@ -7,6 +7,7 @@ describe('ng2 compiler benchmark', function() {
|
||||||
afterEach(verifyNoBrowserErrors);
|
afterEach(verifyNoBrowserErrors);
|
||||||
|
|
||||||
it('should log withBindings stats', function(done) {
|
it('should log withBindings stats', function(done) {
|
||||||
|
browser.sleep(1000);
|
||||||
runBenchmark({
|
runBenchmark({
|
||||||
url: URL,
|
url: URL,
|
||||||
id: 'ng2.compile.withBindings',
|
id: 'ng2.compile.withBindings',
|
||||||
|
@ -19,6 +20,7 @@ describe('ng2 compiler benchmark', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should log noBindings stats', function(done) {
|
it('should log noBindings stats', function(done) {
|
||||||
|
browser.sleep(1000);
|
||||||
runBenchmark({
|
runBenchmark({
|
||||||
url: URL,
|
url: URL,
|
||||||
id: 'ng2.compile.noBindings',
|
id: 'ng2.compile.noBindings',
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<h2>Params</h2>
|
<h2>Params</h2>
|
||||||
<form>
|
<form>
|
||||||
Elements:
|
Elements:
|
||||||
<input type="number" name="elements" placeholder="elements" value="150">
|
<input type="number" name="elements" placeholder="elements" value="50">
|
||||||
<br>
|
<br>
|
||||||
<button>Apply</button>
|
<button>Apply</button>
|
||||||
</form>
|
</form>
|
||||||
|
@ -15,6 +15,8 @@
|
||||||
<button id="compileWithBindings">CompileWithBindings</button>
|
<button id="compileWithBindings">CompileWithBindings</button>
|
||||||
<button id="compileNoBindings">CompileNoBindings</button>
|
<button id="compileNoBindings">CompileNoBindings</button>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<app></app>
|
||||||
$SCRIPTS$
|
$SCRIPTS$
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -1,82 +1,112 @@
|
||||||
|
import {bootstrap} from 'angular2/bootstrap';
|
||||||
import {BrowserDomAdapter} from 'angular2/src/core/dom/browser_adapter';
|
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 {PromiseWrapper} from 'angular2/src/core/facade/async';
|
||||||
import {ListWrapper, Map, MapWrapper} from 'angular2/src/core/facade/collection';
|
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 {
|
import {
|
||||||
Parser,
|
Compiler,
|
||||||
Lexer,
|
Component,
|
||||||
|
Directive,
|
||||||
|
View,
|
||||||
|
ViewContainerRef,
|
||||||
|
bind,
|
||||||
|
Binding,
|
||||||
|
NgIf,
|
||||||
|
ViewMetadata
|
||||||
|
} from 'angular2/core';
|
||||||
|
|
||||||
|
import {CompilerCache} from 'angular2/src/core/compiler/compiler';
|
||||||
|
import {
|
||||||
|
ChangeDetection,
|
||||||
DynamicChangeDetection
|
DynamicChangeDetection
|
||||||
} from 'angular2/src/core/change_detection/change_detection';
|
} 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 {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 {getIntParameter, bindAction} from 'angular2/src/test_lib/benchmark_util';
|
||||||
|
|
||||||
import {ProtoViewFactory} from 'angular2/src/core/compiler/proto_view_factory';
|
function _createBindings(): Binding[] {
|
||||||
import {
|
var multiplyTemplatesBy = getIntParameter('elements');
|
||||||
ViewLoader,
|
return [
|
||||||
DefaultDomCompiler,
|
bind(ViewResolver)
|
||||||
SharedStylesHost,
|
.toFactory(() => new MultiplyViewResolver(
|
||||||
TemplateCloner
|
multiplyTemplatesBy,
|
||||||
} from 'angular2/src/core/render/render';
|
[BenchmarkComponentNoBindings, BenchmarkComponentWithBindings]),
|
||||||
import {
|
[]),
|
||||||
DomElementSchemaRegistry
|
// Use DynamicChangeDetector as that is the only one that Dart supports as well
|
||||||
} from 'angular2/src/core/render/dom/schema/dom_element_schema_registry';
|
// so that we can compare the numbers between JS and Dart
|
||||||
|
bind(ChangeDetection).toClass(DynamicChangeDetection)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
BrowserDomAdapter.makeCurrent();
|
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();
|
function measureWrapper(func, desc) {
|
||||||
var reader = new DirectiveResolver();
|
return function() {
|
||||||
var pipeResolver = new PipeResolver();
|
var begin = DateWrapper.now();
|
||||||
var cache = new CompilerCache();
|
print(`[${desc}] Begin...`);
|
||||||
var viewResolver = new MultipleViewResolver(
|
var onSuccess = function(_) {
|
||||||
count, [BenchmarkComponentNoBindings, BenchmarkComponentWithBindings]);
|
var elapsedMs = DateWrapper.toMillis(DateWrapper.now()) - DateWrapper.toMillis(begin);
|
||||||
var urlResolver = new UrlResolver();
|
print(`[${desc}] ...done, took ${elapsedMs} ms`);
|
||||||
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);
|
|
||||||
};
|
};
|
||||||
|
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() {
|
_fillCache(component: Type) {
|
||||||
cache.clear();
|
var view = super.resolve(component);
|
||||||
return compiler.compileInHost(BenchmarkComponentNoBindings);
|
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() {
|
resolve(component: Type): ViewMetadata {
|
||||||
cache.clear();
|
var result = this._cache.get(component);
|
||||||
return compiler.compileInHost(BenchmarkComponentWithBindings);
|
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'));
|
compileWithBindings() {
|
||||||
bindAction('#compileWithBindings', measureWrapper(compileWithBindings, 'With Bindings'));
|
this._compilerCache.clear();
|
||||||
|
return this._compiler.compileInHost(BenchmarkComponentWithBindings);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Directive({selector: '[dir0]', properties: ['prop: attr0']})
|
@Directive({selector: '[dir0]', properties: ['prop: attr0']})
|
||||||
|
@ -103,32 +133,6 @@ class Dir4 {
|
||||||
constructor(dir3: Dir3) {}
|
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'})
|
@Component({selector: 'cmp-nobind'})
|
||||||
@View({
|
@View({
|
||||||
|
|
Loading…
Reference in New Issue