refactor(perf): use webdriver to execute benchmarks
- use performance log of chromedriver / appium to get timeline data for calculating metrics for benchmarks - change all benchmarks to be made of a standalone application and a protractor test that collectes timeline data - fix and simplify benchmarks - add dart2js to build - remove benchpress Closes #330
This commit is contained in:
@ -0,0 +1,10 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<body>
|
||||
|
||||
<button id="ng2DetectChanges">Ng2 detect changes</button>
|
||||
<button id="baselineDetectChanges">baseline detect changes</button>
|
||||
|
||||
$SCRIPTS$
|
||||
|
||||
</body>
|
@ -3,7 +3,7 @@ import {Parser} from 'change_detection/parser/parser';
|
||||
import {Lexer} from 'change_detection/parser/lexer';
|
||||
import {reflector} from 'reflection/reflection';
|
||||
import {isPresent} from 'facade/lang';
|
||||
import {benchmark, benchmarkStep} from 'benchpress/benchpress';
|
||||
import {document, DOM} from 'facade/dom';
|
||||
|
||||
import {
|
||||
ChangeDetector,
|
||||
@ -12,7 +12,7 @@ import {
|
||||
} from 'change_detection/change_detector';
|
||||
|
||||
|
||||
var ITERATIONS = 200000;
|
||||
var ITERATIONS = 500000;
|
||||
|
||||
class Obj {
|
||||
field0;
|
||||
@ -155,28 +155,25 @@ function setUpChangeDetection() {
|
||||
|
||||
export function main () {
|
||||
setUpReflector();
|
||||
var baselineHead = setUpBaseline();
|
||||
var ng2ChangeDetector = setUpChangeDetection();
|
||||
|
||||
benchmark(`Baseline`, function () {
|
||||
var head = setUpBaseline();
|
||||
|
||||
benchmarkStep('run', function () {
|
||||
var current = head;
|
||||
while (isPresent(current)) {
|
||||
if (current.getter(current.obj) !== current.previousValue) {
|
||||
throw "should not happen";
|
||||
}
|
||||
current = current.next;
|
||||
function baselineDetectChanges(_) {
|
||||
var current = baselineHead;
|
||||
while (isPresent(current)) {
|
||||
if (current.getter(current.obj) !== current.previousValue) {
|
||||
throw "should not happen";
|
||||
}
|
||||
});
|
||||
});
|
||||
current = current.next;
|
||||
}
|
||||
}
|
||||
|
||||
benchmark(`Change Detection`, function() {
|
||||
var cd = setUpChangeDetection();
|
||||
function ng2DetectChanges(_) {
|
||||
ng2ChangeDetector.detectChanges();
|
||||
}
|
||||
|
||||
benchmarkStep('run', function() {
|
||||
cd.detectChanges();
|
||||
});
|
||||
});
|
||||
DOM.on(DOM.querySelector(document, '#ng2DetectChanges'), 'click', ng2DetectChanges);
|
||||
DOM.on(DOM.querySelector(document, '#baselineDetectChanges'), 'click', baselineDetectChanges);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1 +0,0 @@
|
||||
$SCRIPTS$
|
@ -1,5 +0,0 @@
|
||||
import * as change_detection_benchmark from './change_detection_benchmark';
|
||||
|
||||
export function main() {
|
||||
change_detection_benchmark.main();
|
||||
}
|
@ -1,4 +1,9 @@
|
||||
$SCRIPTS$
|
||||
<!doctype html>
|
||||
<html>
|
||||
<body>
|
||||
|
||||
<button id="compileWithBindings">Compile template with bindings</button>
|
||||
<button id="compileNoBindings">Compile template without bindings</button>
|
||||
|
||||
<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">
|
||||
@ -30,3 +35,8 @@ $SCRIPTS$
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
$SCRIPTS$
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,5 +1,3 @@
|
||||
import {benchmark, benchmarkStep} from 'benchpress/benchpress';
|
||||
|
||||
import {DOM, document} from 'facade/dom';
|
||||
import {isBlank, Type} from 'facade/lang';
|
||||
import {MapWrapper} from 'facade/collection';
|
||||
@ -20,10 +18,7 @@ import {reflector} from 'reflection/reflection';
|
||||
|
||||
var COUNT = 30;
|
||||
|
||||
var compiler;
|
||||
var annotatedComponent;
|
||||
|
||||
function setup() {
|
||||
function setupReflector() {
|
||||
reflector.registerType(BenchmarkComponent, {
|
||||
"factory": () => new BenchmarkComponent(),
|
||||
"parameters": [],
|
||||
@ -79,47 +74,34 @@ function setup() {
|
||||
|
||||
"prop": (a,v) => a.prop = v
|
||||
});
|
||||
|
||||
var reader = new CachingDirectiveMetadataReader();
|
||||
compiler = new Compiler(null, reader, new Parser(new Lexer()), new CompilerCache());
|
||||
annotatedComponent = reader.annotatedType(BenchmarkComponent);
|
||||
}
|
||||
|
||||
export function main() {
|
||||
setup();
|
||||
setupReflector();
|
||||
var reader = new DirectiveMetadataReader();
|
||||
var cache = new CompilerCache();
|
||||
var compiler = new Compiler(null, reader, new Parser(new Lexer()), cache);
|
||||
var annotatedComponent = reader.annotatedType(BenchmarkComponent);
|
||||
|
||||
benchmark(`Compiler.compile 5*${COUNT} element no bindings`, function() {
|
||||
var template = loadTemplate('templateNoBindings', COUNT);
|
||||
var templateNoBindings = loadTemplate('templateNoBindings', COUNT);
|
||||
var templateWithBindings = loadTemplate('templateWithBindings', COUNT);
|
||||
|
||||
benchmarkStep('run', function() {
|
||||
// Need to clone every time as the compiler might modify the template!
|
||||
var cloned = DOM.clone(template);
|
||||
compiler.compileAllLoaded(null, annotatedComponent, cloned);
|
||||
});
|
||||
});
|
||||
function compileNoBindings(_) {
|
||||
// Need to clone every time as the compiler might modify the template!
|
||||
var cloned = DOM.clone(templateNoBindings);
|
||||
cache.clear();
|
||||
compiler.compileAllLoaded(null, annotatedComponent, cloned);
|
||||
}
|
||||
|
||||
benchmark(`Compiler.compile 5*${COUNT} element with bindings`, function() {
|
||||
var template = loadTemplate('templateWithBindings', COUNT);
|
||||
function compileWithBindings(_) {
|
||||
// Need to clone every time as the compiler might modify the template!
|
||||
var cloned = DOM.clone(templateWithBindings);
|
||||
cache.clear();
|
||||
compiler.compileAllLoaded(null, annotatedComponent, cloned);
|
||||
}
|
||||
|
||||
benchmarkStep('run', function() {
|
||||
// Need to clone every time as the compiler might modify the template!
|
||||
var cloned = DOM.clone(template);
|
||||
compiler.compileAllLoaded(null, annotatedComponent, cloned);
|
||||
});
|
||||
});
|
||||
|
||||
benchmark(`instantiate 5*${COUNT} element with bindings`, function() {
|
||||
var template = loadTemplate('templateWithBindings', COUNT);
|
||||
var protoView = compiler.compileWithCache(null, annotatedComponent, template);
|
||||
var rootRecordRange = new ProtoRecordRange().instantiate(null, null);
|
||||
|
||||
benchmarkStep('run', function() {
|
||||
var view = protoView.instantiate(null, null, null);
|
||||
// also include adding / removing the RecordRange from the parent in the benchmark.
|
||||
rootRecordRange.addRange(view.recordRange);
|
||||
view.recordRange.remove();
|
||||
});
|
||||
});
|
||||
DOM.on(DOM.querySelector(document, '#compileNoBindings'), 'click', compileNoBindings);
|
||||
DOM.on(DOM.querySelector(document, '#compileWithBindings'), 'click', compileWithBindings);
|
||||
}
|
||||
|
||||
function loadTemplate(templateId, repeatCount) {
|
||||
@ -132,22 +114,6 @@ function loadTemplate(templateId, repeatCount) {
|
||||
return DOM.createTemplate(result);
|
||||
}
|
||||
|
||||
// Caching reflector as reflection in Dart using Mirrors
|
||||
class CachingDirectiveMetadataReader extends DirectiveMetadataReader {
|
||||
_cache: Map;
|
||||
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({
|
||||
selector: '[dir0]',
|
||||
bind: {
|
||||
|
@ -1,7 +0,0 @@
|
||||
import * as sbm from './selector_benchmark';
|
||||
import * as cbm from './compiler_benchmark';
|
||||
|
||||
export function main() {
|
||||
sbm.main();
|
||||
cbm.main();
|
||||
}
|
12
modules/benchmarks/src/compiler/selector_benchmark.html
Normal file
12
modules/benchmarks/src/compiler/selector_benchmark.html
Normal file
@ -0,0 +1,12 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<body>
|
||||
|
||||
<button id="parse">Selector.parse</button>
|
||||
<button id="addSelectable">Selector.addSelectable</button>
|
||||
<button id="match">Selector.match</button>
|
||||
|
||||
$SCRIPTS$
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,63 +1,56 @@
|
||||
import {benchmark, benchmarkStep} from 'benchpress/benchpress';
|
||||
import {document, DOM} from 'facade/dom';
|
||||
|
||||
import {SelectorMatcher} from "core/compiler/selector";
|
||||
import {CssSelector} from "core/compiler/selector";
|
||||
import {StringWrapper, Math} from 'facade/lang';
|
||||
import {ListWrapper} from 'facade/collection';
|
||||
|
||||
var fixedMatcher;
|
||||
var fixedSelectorStrings = [];
|
||||
var fixedSelectors = [];
|
||||
|
||||
var COUNT = 1000;
|
||||
|
||||
export function main() {
|
||||
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++) {
|
||||
var fixedMatcher;
|
||||
var fixedSelectorStrings = [];
|
||||
var fixedSelectors = [];
|
||||
for (var i=0; i<COUNT; i++) {
|
||||
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]));
|
||||
}
|
||||
fixedMatcher = new SelectorMatcher();
|
||||
for (var i=0; i<count; i++) {
|
||||
for (var i=0; i<COUNT; i++) {
|
||||
fixedMatcher.addSelectable(fixedSelectors[i], i);
|
||||
}
|
||||
|
||||
function parse(_) {
|
||||
var result = [];
|
||||
for (var i=0; i<COUNT; i++) {
|
||||
ListWrapper.push(result, CssSelector.parse(fixedSelectorStrings[i]));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function addSelectable(_) {
|
||||
var matcher = new SelectorMatcher();
|
||||
for (var i=0; i<COUNT; i++) {
|
||||
matcher.addSelectable(fixedSelectors[i], i);
|
||||
}
|
||||
return matcher;
|
||||
}
|
||||
|
||||
function match(_) {
|
||||
var matchCount = 0;
|
||||
for (var i=0; i<COUNT; i++) {
|
||||
fixedMatcher.match(fixedSelectors[i], (selected) => {
|
||||
matchCount += selected;
|
||||
});
|
||||
}
|
||||
return matchCount;
|
||||
}
|
||||
|
||||
DOM.on(DOM.querySelector(document, '#parse'), 'click', parse);
|
||||
DOM.on(DOM.querySelector(document, '#addSelectable'), 'click', addSelectable);
|
||||
DOM.on(DOM.querySelector(document, '#match'), 'click', match);
|
||||
}
|
||||
|
||||
function randomSelector() {
|
||||
|
12
modules/benchmarks/src/di/di_benchmark.html
Normal file
12
modules/benchmarks/src/di/di_benchmark.html
Normal file
@ -0,0 +1,12 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<body>
|
||||
|
||||
<button id="getByToken">Injector.get (token)</button>
|
||||
<button id="getByKey">Injector.get (key)</button>
|
||||
<button id="getChild">Injector.get (grand x 5 child)</button>
|
||||
<button id="instantiate">Injector.instantiate</button>
|
||||
|
||||
$SCRIPTS$
|
||||
</body>
|
||||
</html>
|
113
modules/benchmarks/src/di/di_benchmark.js
Normal file
113
modules/benchmarks/src/di/di_benchmark.js
Normal file
@ -0,0 +1,113 @@
|
||||
import {Injector, Key} from "di/di";
|
||||
import {reflector} from 'reflection/reflection';
|
||||
import {document, DOM} from 'facade/dom';
|
||||
|
||||
var count = 0;
|
||||
|
||||
function setupReflector() {
|
||||
reflector.registerType(A, {
|
||||
'factory': () => new A(),
|
||||
'parameters': [],
|
||||
'annotations' : []
|
||||
});
|
||||
reflector.registerType(B, {
|
||||
'factory': (a) => new B(a),
|
||||
'parameters': [[A]],
|
||||
'annotations' : []
|
||||
});
|
||||
reflector.registerType(C, {
|
||||
'factory': (b) => new C(b),
|
||||
'parameters': [[B]],
|
||||
'annotations' : []
|
||||
});
|
||||
reflector.registerType(D, {
|
||||
'factory': (c,b) => new D(c,b),
|
||||
'parameters': [[C],[B]],
|
||||
'annotations' : []
|
||||
});
|
||||
reflector.registerType(E, {
|
||||
'factory': (d,c) => new E(d,c),
|
||||
'parameters': [[D],[C]],
|
||||
'annotations' : []
|
||||
});
|
||||
}
|
||||
|
||||
export function main() {
|
||||
setupReflector();
|
||||
var bindings = [A, B, C, D, E];
|
||||
var injector = new Injector(bindings);
|
||||
|
||||
var D_KEY = Key.get(D);
|
||||
var E_KEY = Key.get(E);
|
||||
var childInjector = injector.
|
||||
createChild([]).
|
||||
createChild([]).
|
||||
createChild([]).
|
||||
createChild([]).
|
||||
createChild([]);
|
||||
|
||||
function getByToken (_) {
|
||||
for (var i = 0; i < 20000; ++i) {
|
||||
injector.get(D);
|
||||
injector.get(E);
|
||||
}
|
||||
}
|
||||
function getByKey(_) {
|
||||
for (var i = 0; i < 20000; ++i) {
|
||||
injector.get(D_KEY);
|
||||
injector.get(E_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
function getChild (_) {
|
||||
for (var i = 0; i < 20000; ++i) {
|
||||
childInjector.get(D);
|
||||
childInjector.get(E);
|
||||
}
|
||||
}
|
||||
|
||||
function instantiate (_) {
|
||||
for (var i = 0; i < 5000; ++i) {
|
||||
var child = injector.createChild([E]);
|
||||
child.get(E);
|
||||
}
|
||||
}
|
||||
|
||||
DOM.on(DOM.querySelector(document, '#getByToken'), 'click', getByToken);
|
||||
DOM.on(DOM.querySelector(document, '#getByKey'), 'click', getByKey);
|
||||
DOM.on(DOM.querySelector(document, '#getChild'), 'click', getChild);
|
||||
DOM.on(DOM.querySelector(document, '#instantiate'), 'click', instantiate);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
class A {
|
||||
constructor() {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
class B {
|
||||
constructor(a:A) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
class C {
|
||||
constructor(b:B) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
class D {
|
||||
constructor(c:C, b:B) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
class E {
|
||||
constructor(d:D, c:C) {
|
||||
count++;
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
import {Injector} from "di/di";
|
||||
|
||||
var count = 0;
|
||||
|
||||
export function run () {
|
||||
var bindings = [A, B, C, D, E];
|
||||
var injector = new Injector(bindings);
|
||||
|
||||
for (var i = 0; i < 20000; ++i) {
|
||||
injector.get(D);
|
||||
injector.get(E);
|
||||
}
|
||||
}
|
||||
|
||||
class A {
|
||||
constructor() {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
class B {
|
||||
constructor(a:A) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
class C {
|
||||
constructor(b:B) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
class D {
|
||||
constructor(c:C, b:B) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
class E {
|
||||
constructor(d:D, c:C) {
|
||||
count++;
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
import {Injector, Key} from "di/di";
|
||||
|
||||
var count = 0;
|
||||
|
||||
export function run () {
|
||||
var bindings = [A, B, C, D, E];
|
||||
var injector = new Injector(bindings);
|
||||
|
||||
var D_KEY = Key.get(D);
|
||||
var E_KEY = Key.get(E);
|
||||
|
||||
for (var i = 0; i < 20000; ++i) {
|
||||
injector.get(D_KEY);
|
||||
injector.get(E_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
class A {
|
||||
constructor() {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
class B {
|
||||
constructor(a:A) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
class C {
|
||||
constructor(b:B) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
class D {
|
||||
constructor(c:C, b:B) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
class E {
|
||||
constructor(d:D, c:C) {
|
||||
count++;
|
||||
}
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
import {Injector, Key} from "di/di";
|
||||
|
||||
var count = 0;
|
||||
|
||||
export function run () {
|
||||
var bindings = [A, B, C, D, E];
|
||||
var injector = new Injector(bindings);
|
||||
var childInjector = injector.
|
||||
createChild([]).
|
||||
createChild([]).
|
||||
createChild([]).
|
||||
createChild([]).
|
||||
createChild([]);
|
||||
|
||||
for (var i = 0; i < 20000; ++i) {
|
||||
childInjector.get(D);
|
||||
childInjector.get(E);
|
||||
}
|
||||
}
|
||||
|
||||
class A {
|
||||
constructor() {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
class B {
|
||||
constructor(a:A) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
class C {
|
||||
constructor(b:B) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
class D {
|
||||
constructor(c:C, b:B) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
class E {
|
||||
constructor(d:D, c:C) {
|
||||
count++;
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
import {Injector, Key} from "di/di";
|
||||
|
||||
var count = 0;
|
||||
|
||||
export function run () {
|
||||
var bindings = [A, B, C, D];
|
||||
var injector = new Injector(bindings);
|
||||
|
||||
for (var i = 0; i < 1000; ++i) {
|
||||
var child = injector.createChild([E]);
|
||||
child.get(E);
|
||||
}
|
||||
}
|
||||
|
||||
class A {
|
||||
constructor() {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
class B {
|
||||
constructor(a:A) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
class C {
|
||||
constructor(b:B) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
class D {
|
||||
constructor(c:C, b:B) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
class E {
|
||||
constructor(d:D, c:C) {
|
||||
count++;
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
$SCRIPTS$
|
@ -1,24 +0,0 @@
|
||||
import * as injector_get_benchmark from './injector_get_benchmark';
|
||||
import * as injector_get_by_key_benchmark from './injector_get_by_key_benchmark';
|
||||
import * as injector_get_child_benchmark from './injector_get_child_benchmark';
|
||||
import * as injector_instantiate_benchmark from './injector_instantiate_benchmark';
|
||||
|
||||
import {benchmark, benchmarkStep} from 'benchpress/benchpress';
|
||||
|
||||
export function main() {
|
||||
benchmark(`Injector.get (token)`, function() {
|
||||
benchmarkStep('run', injector_get_benchmark.run);
|
||||
});
|
||||
|
||||
benchmark(`Injector.get (key)`, function() {
|
||||
benchmarkStep('run', injector_get_by_key_benchmark.run);
|
||||
});
|
||||
|
||||
benchmark(`Injector.get (grand x 5 child)`, function() {
|
||||
benchmarkStep('run', injector_get_child_benchmark.run);
|
||||
});
|
||||
|
||||
benchmark(`Injector.instantiate`, function() {
|
||||
benchmarkStep('run', injector_instantiate_benchmark.run);
|
||||
});
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<body>
|
||||
|
||||
<button id="instantiate">ElementInjector.instantiate</button>
|
||||
<button id="instantiateDirectives">ElementInjector.instantiateDirectives</button>
|
||||
|
||||
$SCRIPTS$
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,69 @@
|
||||
import {reflector} from 'reflection/reflection';
|
||||
import {Injector} from 'di/di';
|
||||
import {ProtoElementInjector} from 'core/compiler/element_injector';
|
||||
import {document, DOM} from 'facade/dom';
|
||||
|
||||
var count = 0;
|
||||
var ITERATIONS = 20000;
|
||||
|
||||
function setupReflector() {
|
||||
reflector.registerType(A, {
|
||||
'factory': () => new A(),
|
||||
'parameters': [],
|
||||
'annotations' : []
|
||||
});
|
||||
reflector.registerType(B, {
|
||||
'factory': () => new B(),
|
||||
'parameters': [],
|
||||
'annotations' : []
|
||||
});
|
||||
reflector.registerType(C, {
|
||||
'factory': (a,b) => new C(a,b),
|
||||
'parameters': [[A],[B]],
|
||||
'annotations' : []
|
||||
});
|
||||
}
|
||||
|
||||
export function main() {
|
||||
setupReflector();
|
||||
var appInjector = new Injector([]);
|
||||
|
||||
var bindings = [A, B, C];
|
||||
var proto = new ProtoElementInjector(null, 0, bindings);
|
||||
var elementInjector = proto.instantiate(null,null);
|
||||
|
||||
function instantiate (_) {
|
||||
for (var i = 0; i < ITERATIONS; ++i) {
|
||||
var ei = proto.instantiate(null, null);
|
||||
ei.instantiateDirectives(appInjector, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
function instantiateDirectives (_) {
|
||||
for (var i = 0; i < ITERATIONS; ++i) {
|
||||
elementInjector.clearDirectives();
|
||||
elementInjector.instantiateDirectives(appInjector, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
DOM.on(DOM.querySelector(document, '#instantiate'), 'click', instantiate);
|
||||
DOM.on(DOM.querySelector(document, '#instantiateDirectives'), 'click', instantiateDirectives);
|
||||
}
|
||||
|
||||
class A {
|
||||
constructor() {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
class B {
|
||||
constructor() {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
class C {
|
||||
constructor(a:A, b:B) {
|
||||
count++;
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
import {Injector} from 'di/di';
|
||||
import {ProtoElementInjector} from 'core/compiler/element_injector';
|
||||
|
||||
var ITERATIONS = 20000;
|
||||
var count = 0;
|
||||
|
||||
export function run () {
|
||||
var appInjector = new Injector([]);
|
||||
|
||||
var bindings = [A, B, C];
|
||||
var proto = new ProtoElementInjector(null, 0, bindings);
|
||||
for (var i = 0; i < ITERATIONS; ++i) {
|
||||
var ei = proto.instantiate(null, null);
|
||||
ei.instantiateDirectives(appInjector, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
class A {
|
||||
constructor() {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
class B {
|
||||
constructor() {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
class C {
|
||||
constructor(a:A, b:B) {
|
||||
count++;
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
import {Binding, Dependency, Key, Injector} from 'di/di';
|
||||
import {ProtoElementInjector} from 'core/compiler/element_injector';
|
||||
|
||||
var ITERATIONS = 20000;
|
||||
var count = 0;
|
||||
|
||||
export function run () {
|
||||
var appInjector = new Injector([]);
|
||||
|
||||
var bindings = [
|
||||
new Binding(Key.get(A), () => new A(), [], false),
|
||||
new Binding(Key.get(B), () => new B(), [], false),
|
||||
new Binding(Key.get(C), (a,b) => new C(a,b), [
|
||||
new Dependency(Key.get(A), false, false, []),
|
||||
new Dependency(Key.get(B), false, false, [])
|
||||
], false)];
|
||||
|
||||
|
||||
var proto = new ProtoElementInjector(null, 0, bindings);
|
||||
for (var i = 0; i < ITERATIONS; ++i) {
|
||||
var ei = proto.instantiate(null,null);
|
||||
ei.instantiateDirectives(appInjector, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
class A {
|
||||
constructor() {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
class B {
|
||||
constructor() {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
class C {
|
||||
constructor(a:A, b:B) {
|
||||
count++;
|
||||
}
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
import {Injector} from 'di/di';
|
||||
import {ProtoElementInjector} from 'core/compiler/element_injector';
|
||||
|
||||
var ITERATIONS = 20000;
|
||||
var count = 0;
|
||||
|
||||
export function run () {
|
||||
var appInjector = new Injector([]);
|
||||
|
||||
var bindings = [A, B, C];
|
||||
var proto = new ProtoElementInjector(null, 0, bindings);
|
||||
var ei = proto.instantiate(null,null);
|
||||
|
||||
for (var i = 0; i < ITERATIONS; ++i) {
|
||||
ei.clearDirectives();
|
||||
ei.instantiateDirectives(appInjector, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
class A {
|
||||
constructor() {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
class B {
|
||||
constructor() {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
class C {
|
||||
constructor(a:A, b:B) {
|
||||
count++;
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
$SCRIPTS$
|
@ -1,19 +0,0 @@
|
||||
import * as instantiate_benchmark from './instantiate_benchmark';
|
||||
import * as instantiate_directive_benchmark from './instantiate_directive_benchmark';
|
||||
import * as instantiate_benchmark_codegen from './instantiate_benchmark_codegen';
|
||||
|
||||
import {benchmark, benchmarkStep} from 'benchpress/benchpress';
|
||||
|
||||
export function main() {
|
||||
benchmark(`ElementInjector.instantiate + instantiateDirectives`, function() {
|
||||
benchmarkStep('run', instantiate_benchmark.run);
|
||||
});
|
||||
|
||||
benchmark(`ElementInjector.instantiateDirectives`, function() {
|
||||
benchmarkStep('run', instantiate_directive_benchmark.run);
|
||||
});
|
||||
|
||||
benchmark(`ElementInjector.instantiate + instantiateDirectives (codegen)`, function() {
|
||||
benchmarkStep('run', instantiate_benchmark_codegen.run);
|
||||
});
|
||||
}
|
25
modules/benchmarks/src/index.html
Normal file
25
modules/benchmarks/src/index.html
Normal file
@ -0,0 +1,25 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<body>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="di/di_benchmark.html">DI benchmark</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="change_detection/change_detection_benchmark.html">Change detection benchmark</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="compiler/selector_benchmark.html">Selector benchmark</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="compiler/compiler_benchmark.html">Compiler benchmark</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="element_injector/element_injector_benchmark.html">Element injector benchmark</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="tree/tree_benchmark.html">Tree benchmark</a>
|
||||
</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
@ -1,5 +0,0 @@
|
||||
$SCRIPTS$
|
||||
|
||||
<app></app>
|
||||
|
||||
<baseline></baseline>
|
@ -1,5 +0,0 @@
|
||||
import * as tree_benchmark from './tree_benchmark';
|
||||
|
||||
export function main() {
|
||||
tree_benchmark.main();
|
||||
}
|
27
modules/benchmarks/src/tree/tree_benchmark.html
Normal file
27
modules/benchmarks/src/tree/tree_benchmark.html
Normal file
@ -0,0 +1,27 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<body>
|
||||
|
||||
<h2>Angular2 tree benchmark</h2>
|
||||
<p>
|
||||
<button id="ng2DestroyDom">destroyDom</button>
|
||||
<button id="ng2CreateDom">createDom</button>
|
||||
</p>
|
||||
|
||||
<h2>Baseline tree benchmark</h2>
|
||||
<p>
|
||||
<button id="baselineDestroyDom">destroyDom</button>
|
||||
<button id="baselineCreateDom">createDom</button>
|
||||
</p>
|
||||
|
||||
<div>
|
||||
<app></app>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<baseline></baseline>
|
||||
</div>
|
||||
|
||||
$SCRIPTS$
|
||||
</body>
|
||||
</html>
|
@ -1,5 +1,3 @@
|
||||
import {benchmark, benchmarkStep} from 'benchpress/benchpress';
|
||||
|
||||
import {ChangeDetector} from 'change_detection/change_detector';
|
||||
import {Parser} from 'change_detection/parser/parser';
|
||||
import {Lexer} from 'change_detection/parser/lexer';
|
||||
@ -9,6 +7,7 @@ import {bootstrap, Component, Template, TemplateConfig, ViewPort, Compiler} from
|
||||
import {CompilerCache} from 'core/compiler/compiler';
|
||||
import {DirectiveMetadataReader} from 'core/compiler/directive_metadata_reader';
|
||||
import {TemplateLoader} from 'core/compiler/template_loader';
|
||||
import {LifeCycle} from 'core/life_cycle/life_cycle';
|
||||
|
||||
import {reflector} from 'reflection/reflection';
|
||||
import {DOM, document, Element} from 'facade/dom';
|
||||
@ -16,7 +15,7 @@ import {isPresent} from 'facade/lang';
|
||||
|
||||
var MAX_DEPTH = 9;
|
||||
|
||||
function setup() {
|
||||
function setupReflector() {
|
||||
// TODO: Put the general calls to reflector.register... in a shared file
|
||||
// as they are needed in all benchmarks...
|
||||
|
||||
@ -98,6 +97,12 @@ function setup() {
|
||||
'annotations': []
|
||||
});
|
||||
|
||||
reflector.registerType(LifeCycle, {
|
||||
"factory": (cd) => new LifeCycle(cd),
|
||||
"parameters": [[ChangeDetector]],
|
||||
"annotations": []
|
||||
});
|
||||
|
||||
|
||||
reflector.registerGetters({
|
||||
'value': (a) => a.value,
|
||||
@ -115,61 +120,62 @@ function setup() {
|
||||
'data': (a,v) => a.data = v,
|
||||
'ngIf': (a,v) => a.ngIf = v
|
||||
});
|
||||
|
||||
return bootstrap(AppComponent);
|
||||
}
|
||||
|
||||
export function main() {
|
||||
setupReflector();
|
||||
|
||||
var app;
|
||||
var changeDetector;
|
||||
setup().then((injector) => {
|
||||
changeDetector = injector.get(ChangeDetector);
|
||||
app = injector.get(AppComponent);
|
||||
});
|
||||
var baselineRootTreeComponent;
|
||||
var count = 0;
|
||||
|
||||
benchmark(`tree benchmark`, function() {
|
||||
var count = 0;
|
||||
function ng2DestroyDom(_) {
|
||||
// TODO: We need an initial value as otherwise the getter for data.value will fail
|
||||
// --> this should be already caught in change detection!
|
||||
app.initData = new TreeNode('', null, null);
|
||||
changeDetector.detectChanges();
|
||||
}
|
||||
|
||||
benchmarkStep(`destroyDom binary tree of depth ${MAX_DEPTH}`, function() {
|
||||
// TODO: We need an initial value as otherwise the getter for data.value will fail
|
||||
// --> this should be already caught in change detection!
|
||||
app.initData = new TreeNode('', null, null);
|
||||
changeDetector.detectChanges();
|
||||
function ng2CreateDom(_) {
|
||||
var values = count++ % 2 == 0 ?
|
||||
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '*'] :
|
||||
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', '-'];
|
||||
|
||||
app.initData = buildTree(MAX_DEPTH, values, 0);
|
||||
changeDetector.detectChanges();
|
||||
}
|
||||
|
||||
function initNg2() {
|
||||
bootstrap(AppComponent).then((injector) => {
|
||||
changeDetector = injector.get(ChangeDetector);
|
||||
app = injector.get(AppComponent);
|
||||
DOM.on(DOM.querySelector(document, '#ng2DestroyDom'), 'click', ng2DestroyDom);
|
||||
DOM.on(DOM.querySelector(document, '#ng2CreateDom'), 'click', ng2CreateDom);
|
||||
});
|
||||
}
|
||||
|
||||
benchmarkStep(`createDom binary tree of depth ${MAX_DEPTH}`, function() {
|
||||
var maxDepth = 9;
|
||||
var values = count++ % 2 == 0 ?
|
||||
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '*'] :
|
||||
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', '-'];
|
||||
function baselineDestroyDom(_) {
|
||||
baselineRootTreeComponent.update(new TreeNode('', null, null));
|
||||
}
|
||||
|
||||
app.initData = buildTree(maxDepth, values, 0);
|
||||
changeDetector.detectChanges();
|
||||
});
|
||||
function baselineCreateDom(_) {
|
||||
var values = count++ % 2 == 0 ?
|
||||
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '*'] :
|
||||
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', '-'];
|
||||
|
||||
});
|
||||
baselineRootTreeComponent.update(buildTree(MAX_DEPTH, values, 0));
|
||||
}
|
||||
|
||||
benchmark(`baseline tree benchmark`, function() {
|
||||
var baselineAppElement = DOM.querySelectorAll(document, 'baseline')[0];
|
||||
var rootTreeComponent = new BaseLineTreeComponent();
|
||||
DOM.appendChild(baselineAppElement, rootTreeComponent.element);
|
||||
function initBaseline() {
|
||||
baselineRootTreeComponent = new BaseLineTreeComponent();
|
||||
DOM.appendChild(DOM.querySelector(document, 'baseline'), baselineRootTreeComponent.element);
|
||||
DOM.on(DOM.querySelector(document, '#baselineDestroyDom'), 'click', baselineDestroyDom);
|
||||
DOM.on(DOM.querySelector(document, '#baselineCreateDom'), 'click', baselineCreateDom);
|
||||
}
|
||||
|
||||
var count = 0;
|
||||
|
||||
benchmarkStep(`destroyDom binary tree of depth ${MAX_DEPTH}`, function() {
|
||||
rootTreeComponent.update(new TreeNode('', null, null));
|
||||
});
|
||||
|
||||
benchmarkStep(`createDom binary tree of depth ${MAX_DEPTH}`, function() {
|
||||
var maxDepth = 9;
|
||||
var values = count++ % 2 == 0 ?
|
||||
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '*'] :
|
||||
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', '-'];
|
||||
|
||||
rootTreeComponent.update(buildTree(maxDepth, values, 0));
|
||||
});
|
||||
|
||||
});
|
||||
initNg2();
|
||||
initBaseline();
|
||||
}
|
||||
|
||||
class TreeNode {
|
||||
|
Reference in New Issue
Block a user