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:
Tobias Bosch
2014-12-22 17:50:10 -08:00
parent d642c6afb5
commit df4ac0dd33
66 changed files with 1146 additions and 985 deletions

View File

@ -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>

View File

@ -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: {

View File

@ -1,7 +0,0 @@
import * as sbm from './selector_benchmark';
import * as cbm from './compiler_benchmark';
export function main() {
sbm.main();
cbm.main();
}

View 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>

View File

@ -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() {