feat(bench press): replace microIterations with microMetrics
This commit is contained in:
parent
3afb744e77
commit
33bfc4c24a
|
@ -1,5 +1,5 @@
|
||||||
import {BrowserDomAdapter} from 'angular2/src/dom/browser_adapter';
|
import {BrowserDomAdapter} from 'angular2/src/dom/browser_adapter';
|
||||||
import {document} from 'angular2/src/facade/browser';
|
import {document, window} from 'angular2/src/facade/browser';
|
||||||
import {NumberWrapper, BaseException, isBlank} from 'angular2/src/facade/lang';
|
import {NumberWrapper, BaseException, isBlank} from 'angular2/src/facade/lang';
|
||||||
|
|
||||||
var DOM = new BrowserDomAdapter();
|
var DOM = new BrowserDomAdapter();
|
||||||
|
@ -34,4 +34,11 @@ export function bindAction(selector:string, callback:Function) {
|
||||||
DOM.on(el, 'click', function(_) {
|
DOM.on(el, 'click', function(_) {
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function microBenchmark(name, iterationCount, callback) {
|
||||||
|
var durationName = `${name}/${iterationCount}`;
|
||||||
|
window.console.time(durationName);
|
||||||
|
callback();
|
||||||
|
window.console.timeEnd(durationName);
|
||||||
|
}
|
||||||
|
|
|
@ -23,26 +23,21 @@ function runBenchmark(config) {
|
||||||
return getScaleFactor(browser.params.benchmark.scaling).then(function(scaleFactor) {
|
return getScaleFactor(browser.params.benchmark.scaling).then(function(scaleFactor) {
|
||||||
var description = {};
|
var description = {};
|
||||||
var urlParams = [];
|
var urlParams = [];
|
||||||
var microIterations = config.microIterations || 0;
|
if (config.params) {
|
||||||
var params = config.params || [];
|
config.params.forEach(function(param) {
|
||||||
if (microIterations) {
|
var name = param.name;
|
||||||
params = params.concat([{
|
var value = applyScaleFactor(param.value, scaleFactor, param.scale);
|
||||||
name: 'iterations', value: microIterations, scale: 'linear'
|
urlParams.push(name + '=' + value);
|
||||||
}]);
|
description[name] = value;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
params.forEach(function(param) {
|
|
||||||
var name = param.name;
|
|
||||||
var value = applyScaleFactor(param.value, scaleFactor, param.scale);
|
|
||||||
urlParams.push(name + '=' + value);
|
|
||||||
description[name] = value;
|
|
||||||
});
|
|
||||||
var url = encodeURI(config.url + '?' + urlParams.join('&'));
|
var url = encodeURI(config.url + '?' + urlParams.join('&'));
|
||||||
browser.get(url);
|
browser.get(url);
|
||||||
return benchpressRunner.sample({
|
return benchpressRunner.sample({
|
||||||
id: config.id,
|
id: config.id,
|
||||||
execute: config.work,
|
execute: config.work,
|
||||||
prepare: config.prepare,
|
prepare: config.prepare,
|
||||||
microIterations: microIterations,
|
microMetrics: config.microMetrics,
|
||||||
bindings: [
|
bindings: [
|
||||||
benchpress.bind(benchpress.Options.SAMPLE_DESCRIPTION).toValue(description)
|
benchpress.bind(benchpress.Options.SAMPLE_DESCRIPTION).toValue(description)
|
||||||
]
|
]
|
||||||
|
|
|
@ -11,10 +11,13 @@ describe('ng2 change detection benchmark', function () {
|
||||||
url: URL,
|
url: URL,
|
||||||
buttons: ['#ng2ChangeDetectionDynamic'],
|
buttons: ['#ng2ChangeDetectionDynamic'],
|
||||||
id: 'ng2.changeDetection.dynamic',
|
id: 'ng2.changeDetection.dynamic',
|
||||||
params: [{
|
params: [
|
||||||
name: 'numberOfChecks', value: 900000
|
{name: 'numberOfChecks', value: 900000},
|
||||||
}],
|
{name: 'iterations', value: 20, scale: 'linear'}
|
||||||
microIterations: 20
|
],
|
||||||
|
microMetrics: {
|
||||||
|
'detectChangesAvg': 'avg time to detect changes (ms)'
|
||||||
|
}
|
||||||
}).then(done, done.fail);
|
}).then(done, done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -23,10 +26,13 @@ describe('ng2 change detection benchmark', function () {
|
||||||
url: URL,
|
url: URL,
|
||||||
buttons: ['#ng2ChangeDetectionJit'],
|
buttons: ['#ng2ChangeDetectionJit'],
|
||||||
id: 'ng2.changeDetection.jit',
|
id: 'ng2.changeDetection.jit',
|
||||||
params: [{
|
params: [
|
||||||
name: 'numberOfChecks', value: 900000
|
{name: 'numberOfChecks', value: 900000},
|
||||||
}],
|
{name: 'iterations', value: 20, scale: 'linear'}
|
||||||
microIterations: 20
|
],
|
||||||
|
microMetrics: {
|
||||||
|
'detectChangesAvg': 'avg time to detect changes (ms)'
|
||||||
|
}
|
||||||
}).then(done, done.fail);
|
}).then(done, done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -35,10 +41,13 @@ describe('ng2 change detection benchmark', function () {
|
||||||
url: URL,
|
url: URL,
|
||||||
buttons: ['#baselineChangeDetection'],
|
buttons: ['#baselineChangeDetection'],
|
||||||
id: 'baseline.changeDetection',
|
id: 'baseline.changeDetection',
|
||||||
params: [{
|
params: [
|
||||||
name: 'numberOfChecks', value: 900000
|
{name: 'numberOfChecks', value: 900000},
|
||||||
}],
|
{name: 'iterations', value: 20, scale: 'linear'}
|
||||||
microIterations: 20
|
],
|
||||||
|
microMetrics: {
|
||||||
|
'detectChangesAvg': 'avg time to detect changes (ms)'
|
||||||
|
}
|
||||||
}).then(done, done.fail);
|
}).then(done, done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,9 @@ describe('ng2 di benchmark', function () {
|
||||||
params: [{
|
params: [{
|
||||||
name: 'iterations', value: 20000, scale: 'linear'
|
name: 'iterations', value: 20000, scale: 'linear'
|
||||||
}],
|
}],
|
||||||
microIterations: 20000
|
microMetrics: {
|
||||||
|
'injectAvg': 'avg time for injection (in ms)'
|
||||||
|
}
|
||||||
}).then(done, done.fail);
|
}).then(done, done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -23,7 +25,12 @@ describe('ng2 di benchmark', function () {
|
||||||
url: URL,
|
url: URL,
|
||||||
buttons: ['#getByKey'],
|
buttons: ['#getByKey'],
|
||||||
id: 'ng2.di.getByKey',
|
id: 'ng2.di.getByKey',
|
||||||
microIterations: 20000
|
params: [{
|
||||||
|
name: 'iterations', value: 20000, scale: 'linear'
|
||||||
|
}],
|
||||||
|
microMetrics: {
|
||||||
|
'injectAvg': 'avg time for injection (in ms)'
|
||||||
|
}
|
||||||
}).then(done, done.fail);
|
}).then(done, done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -32,7 +39,12 @@ describe('ng2 di benchmark', function () {
|
||||||
url: URL,
|
url: URL,
|
||||||
buttons: ['#getChild'],
|
buttons: ['#getChild'],
|
||||||
id: 'ng2.di.getChild',
|
id: 'ng2.di.getChild',
|
||||||
microIterations: 20000
|
params: [{
|
||||||
|
name: 'iterations', value: 20000, scale: 'linear'
|
||||||
|
}],
|
||||||
|
microMetrics: {
|
||||||
|
'injectAvg': 'avg time for getChild (in ms)'
|
||||||
|
}
|
||||||
}).then(done, done.fail);
|
}).then(done, done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -41,7 +53,12 @@ describe('ng2 di benchmark', function () {
|
||||||
url: URL,
|
url: URL,
|
||||||
buttons: ['#instantiate'],
|
buttons: ['#instantiate'],
|
||||||
id: 'ng2.di.instantiate',
|
id: 'ng2.di.instantiate',
|
||||||
microIterations: 10000
|
params: [{
|
||||||
|
name: 'iterations', value: 10000, scale: 'linear'
|
||||||
|
}],
|
||||||
|
microMetrics: {
|
||||||
|
'injectAvg': 'avg time for instantiate (in ms)'
|
||||||
|
}
|
||||||
}).then(done, done.fail);
|
}).then(done, done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,12 @@ describe('ng2 element injector benchmark', function () {
|
||||||
url: URL,
|
url: URL,
|
||||||
buttons: ['#instantiate'],
|
buttons: ['#instantiate'],
|
||||||
id: 'ng2.elementInjector.instantiate',
|
id: 'ng2.elementInjector.instantiate',
|
||||||
microIterations: 20000
|
params: [{
|
||||||
|
name: 'iterations', value: 20000, scale: 'linear'
|
||||||
|
}],
|
||||||
|
microMetrics: {
|
||||||
|
'instantiateAvg': 'avg time for injection (in ms)'
|
||||||
|
}
|
||||||
}).then(done, done.fail);
|
}).then(done, done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -20,7 +25,12 @@ describe('ng2 element injector benchmark', function () {
|
||||||
url: URL,
|
url: URL,
|
||||||
buttons: ['#instantiateDirectives'],
|
buttons: ['#instantiateDirectives'],
|
||||||
id: 'ng2.elementInjector.instantiateDirectives',
|
id: 'ng2.elementInjector.instantiateDirectives',
|
||||||
microIterations: 20000
|
params: [{
|
||||||
|
name: 'iterations', value: 20000, scale: 'linear'
|
||||||
|
}],
|
||||||
|
microMetrics: {
|
||||||
|
'instantiateAvg': 'avg time for injection (in ms)'
|
||||||
|
}
|
||||||
}).then(done, done.fail);
|
}).then(done, done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import {ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
|
import {ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
|
||||||
import {reflector} from 'angular2/src/reflection/reflection';
|
import {reflector} from 'angular2/src/reflection/reflection';
|
||||||
import {isPresent, isJsObject} from 'angular2/src/facade/lang';
|
import {isPresent, isJsObject} from 'angular2/src/facade/lang';
|
||||||
import {getIntParameter, bindAction} from 'angular2/src/test_lib/benchmark_util';
|
import {getIntParameter, bindAction, microBenchmark} from 'angular2/src/test_lib/benchmark_util';
|
||||||
import {BrowserDomAdapter} from 'angular2/src/dom/browser_adapter';
|
import {BrowserDomAdapter} from 'angular2/src/dom/browser_adapter';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -172,7 +172,10 @@ export function main () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
runBaselineChangeDetection();
|
runBaselineChangeDetection();
|
||||||
bindAction('#baselineChangeDetection', baselineChangeDetection);
|
bindAction(
|
||||||
|
'#baselineChangeDetection',
|
||||||
|
() => microBenchmark('detectChangesAvg', numberOfRuns, baselineChangeDetection)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
// -- DYNAMIC
|
// -- DYNAMIC
|
||||||
|
@ -183,7 +186,10 @@ export function main () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ng2DynamicChangeDetector.detectChanges();
|
ng2DynamicChangeDetector.detectChanges();
|
||||||
bindAction('#ng2ChangeDetectionDynamic', ng2ChangeDetectionDynamic);
|
bindAction(
|
||||||
|
'#ng2ChangeDetectionDynamic',
|
||||||
|
() => microBenchmark('detectChangesAvg', numberOfRuns, ng2ChangeDetectionDynamic)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
// -- JIT
|
// -- JIT
|
||||||
|
@ -198,7 +204,10 @@ export function main () {
|
||||||
}
|
}
|
||||||
|
|
||||||
ng2JitChangeDetector.detectChanges();
|
ng2JitChangeDetector.detectChanges();
|
||||||
bindAction('#ng2ChangeDetectionJit', ng2ChangeDetectionJit);
|
bindAction(
|
||||||
|
'#ng2ChangeDetectionJit',
|
||||||
|
() => microBenchmark('detectChangesAvg', numberOfRuns, ng2ChangeDetectionJit)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
bindAction('#ng2ChangeDetectionJit', () => {});
|
bindAction('#ng2ChangeDetectionJit', () => {});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import {Injector, Key} from "angular2/di";
|
import {Injector, Key} from "angular2/di";
|
||||||
import {reflector} from 'angular2/src/reflection/reflection';
|
import {reflector} from 'angular2/src/reflection/reflection';
|
||||||
import {getIntParameter, bindAction} from 'angular2/src/test_lib/benchmark_util';
|
import {getIntParameter, bindAction, microBenchmark} from 'angular2/src/test_lib/benchmark_util';
|
||||||
import {BrowserDomAdapter} from 'angular2/src/dom/browser_adapter';
|
import {BrowserDomAdapter} from 'angular2/src/dom/browser_adapter';
|
||||||
|
|
||||||
var count = 0;
|
var count = 0;
|
||||||
|
@ -77,10 +77,22 @@ export function main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bindAction('#getByToken', getByToken);
|
bindAction(
|
||||||
bindAction('#getByKey', getByKey);
|
'#getByToken',
|
||||||
bindAction('#getChild', getChild);
|
() => microBenchmark('injectAvg', iterations, getByToken)
|
||||||
bindAction('#instantiate', instantiate);
|
);
|
||||||
|
bindAction(
|
||||||
|
'#getByKey',
|
||||||
|
() => microBenchmark('injectAvg', iterations, getByKey)
|
||||||
|
);
|
||||||
|
bindAction(
|
||||||
|
'#getChild',
|
||||||
|
() => microBenchmark('injectAvg', iterations, getChild)
|
||||||
|
);
|
||||||
|
bindAction(
|
||||||
|
'#instantiate',
|
||||||
|
() => microBenchmark('injectAvg', iterations, instantiate)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import {reflector} from 'angular2/src/reflection/reflection';
|
import {reflector} from 'angular2/src/reflection/reflection';
|
||||||
import {Injector} from 'angular2/di';
|
import {Injector} from 'angular2/di';
|
||||||
import {ProtoElementInjector} from 'angular2/src/core/compiler/element_injector';
|
import {ProtoElementInjector} from 'angular2/src/core/compiler/element_injector';
|
||||||
import {getIntParameter, bindAction} from 'angular2/src/test_lib/benchmark_util';
|
import {getIntParameter, bindAction, microBenchmark} from 'angular2/src/test_lib/benchmark_util';
|
||||||
import {BrowserDomAdapter} from 'angular2/src/dom/browser_adapter';
|
import {BrowserDomAdapter} from 'angular2/src/dom/browser_adapter';
|
||||||
|
|
||||||
var count = 0;
|
var count = 0;
|
||||||
|
@ -49,8 +49,14 @@ export function main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bindAction('#instantiate', instantiate);
|
bindAction(
|
||||||
bindAction('#instantiateDirectives', instantiateDirectives);
|
'#instantiate',
|
||||||
|
() => microBenchmark('instantiateAvg', iterations, instantiate)
|
||||||
|
);
|
||||||
|
bindAction(
|
||||||
|
'#instantiateDirectives',
|
||||||
|
() => microBenchmark('instantiateAvg', iterations, instantiateDirectives)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class A {
|
class A {
|
||||||
|
|
|
@ -20,15 +20,11 @@ export class Options {
|
||||||
// TODO(tbosch): use static initializer when our transpiler supports it
|
// TODO(tbosch): use static initializer when our transpiler supports it
|
||||||
static get USER_AGENT() { return _USER_AGENT; }
|
static get USER_AGENT() { return _USER_AGENT; }
|
||||||
// TODO(tbosch): use static initializer when our transpiler supports it
|
// TODO(tbosch): use static initializer when our transpiler supports it
|
||||||
/**
|
|
||||||
* Number of iterations that run inside the browser by user code.
|
|
||||||
* Used for micro benchmarks.
|
|
||||||
**/
|
|
||||||
static get MICRO_ITERATIONS() { return _MICRO_ITERATIONS; }
|
|
||||||
// TODO(tbosch): use static initializer when our transpiler supports it
|
|
||||||
static get NOW() { return _NOW; }
|
static get NOW() { return _NOW; }
|
||||||
// TODO(tbosch): use static values when our transpiler supports them
|
// TODO(tbosch): use static values when our transpiler supports them
|
||||||
static get WRITE_FILE() { return _WRITE_FILE; }
|
static get WRITE_FILE() { return _WRITE_FILE; }
|
||||||
|
// TODO(tbosch): use static values when our transpiler supports them
|
||||||
|
static get MICRO_METRICS() { return _MICRO_METRICS; }
|
||||||
}
|
}
|
||||||
|
|
||||||
var _SAMPLE_ID = new OpaqueToken('Options.sampleId');
|
var _SAMPLE_ID = new OpaqueToken('Options.sampleId');
|
||||||
|
@ -39,7 +35,7 @@ var _PREPARE = new OpaqueToken('Options.prepare');
|
||||||
var _EXECUTE = new OpaqueToken('Options.execute');
|
var _EXECUTE = new OpaqueToken('Options.execute');
|
||||||
var _CAPABILITIES = new OpaqueToken('Options.capabilities');
|
var _CAPABILITIES = new OpaqueToken('Options.capabilities');
|
||||||
var _USER_AGENT = new OpaqueToken('Options.userAgent');
|
var _USER_AGENT = new OpaqueToken('Options.userAgent');
|
||||||
var _MICRO_ITERATIONS = new OpaqueToken('Options.microIterations');
|
var _MICRO_METRICS = new OpaqueToken('Options.microMetrics');
|
||||||
var _NOW = new OpaqueToken('Options.now');
|
var _NOW = new OpaqueToken('Options.now');
|
||||||
var _WRITE_FILE = new OpaqueToken('Options.writeFile');
|
var _WRITE_FILE = new OpaqueToken('Options.writeFile');
|
||||||
|
|
||||||
|
@ -48,5 +44,6 @@ var _DEFAULT_BINDINGS = [
|
||||||
bind(_SAMPLE_DESCRIPTION).toValue({}),
|
bind(_SAMPLE_DESCRIPTION).toValue({}),
|
||||||
bind(_FORCE_GC).toValue(false),
|
bind(_FORCE_GC).toValue(false),
|
||||||
bind(_PREPARE).toValue(false),
|
bind(_PREPARE).toValue(false),
|
||||||
|
bind(_MICRO_METRICS).toValue({}),
|
||||||
bind(_NOW).toValue( () => DateWrapper.now() )
|
bind(_NOW).toValue( () => DateWrapper.now() )
|
||||||
];
|
];
|
|
@ -1,5 +1,7 @@
|
||||||
import { PromiseWrapper, Promise } from 'angular2/src/facade/async';
|
import { PromiseWrapper, Promise } from 'angular2/src/facade/async';
|
||||||
import { isPresent, isBlank, int, BaseException, StringWrapper, Math } from 'angular2/src/facade/lang';
|
import {
|
||||||
|
isPresent, isBlank, int, BaseException, StringWrapper, Math, RegExpWrapper, NumberWrapper
|
||||||
|
} from 'angular2/src/facade/lang';
|
||||||
import { ListWrapper, StringMap, StringMapWrapper } from 'angular2/src/facade/collection';
|
import { ListWrapper, StringMap, StringMapWrapper } from 'angular2/src/facade/collection';
|
||||||
import { bind, OpaqueToken } from 'angular2/di';
|
import { bind, OpaqueToken } from 'angular2/di';
|
||||||
|
|
||||||
|
@ -20,22 +22,21 @@ export class PerflogMetric extends Metric {
|
||||||
_remainingEvents:List;
|
_remainingEvents:List;
|
||||||
_measureCount:int;
|
_measureCount:int;
|
||||||
_setTimeout:Function;
|
_setTimeout:Function;
|
||||||
_microIterations:int;
|
_microMetrics:StringMap<string, string>;
|
||||||
_perfLogFeatures:PerfLogFeatures;
|
_perfLogFeatures:PerfLogFeatures;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param driverExtension
|
* @param driverExtension
|
||||||
* @param setTimeout
|
* @param setTimeout
|
||||||
* @param microIterations Number of iterations that run inside the browser by user code.
|
* @param microMetrics Name and description of metrics provided via console.time / console.timeEnd
|
||||||
* Used for micro benchmarks.
|
|
||||||
**/
|
**/
|
||||||
constructor(driverExtension:WebDriverExtension, setTimeout:Function, microIterations:int) {
|
constructor(driverExtension:WebDriverExtension, setTimeout:Function, microMetrics:StringMap<string, string>) {
|
||||||
super();
|
super();
|
||||||
this._driverExtension = driverExtension;
|
this._driverExtension = driverExtension;
|
||||||
this._remainingEvents = [];
|
this._remainingEvents = [];
|
||||||
this._measureCount = 0;
|
this._measureCount = 0;
|
||||||
this._setTimeout = setTimeout;
|
this._setTimeout = setTimeout;
|
||||||
this._microIterations = microIterations;
|
this._microMetrics = microMetrics;
|
||||||
this._perfLogFeatures = driverExtension.perfLogFeatures();
|
this._perfLogFeatures = driverExtension.perfLogFeatures();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,9 +53,9 @@ export class PerflogMetric extends Metric {
|
||||||
res['gcAmount'] = 'gc amount in kbytes';
|
res['gcAmount'] = 'gc amount in kbytes';
|
||||||
res['majorGcTime'] = 'time of major gcs in ms';
|
res['majorGcTime'] = 'time of major gcs in ms';
|
||||||
}
|
}
|
||||||
if (this._microIterations > 0) {
|
StringMapWrapper.forEach(this._microMetrics, (desc, name) => {
|
||||||
res['microScriptTimeAvg'] = 'average script time for a micro iteration';
|
StringMapWrapper.set(res, name, desc);
|
||||||
}
|
});
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,6 +138,9 @@ export class PerflogMetric extends Metric {
|
||||||
if (this._perfLogFeatures.render) {
|
if (this._perfLogFeatures.render) {
|
||||||
result['renderTime'] = 0;
|
result['renderTime'] = 0;
|
||||||
}
|
}
|
||||||
|
StringMapWrapper.forEach(this._microMetrics, (desc, name) => {
|
||||||
|
result[name] = 0;
|
||||||
|
});
|
||||||
|
|
||||||
var markStartEvent = null;
|
var markStartEvent = null;
|
||||||
var markEndEvent = null;
|
var markEndEvent = null;
|
||||||
|
@ -147,17 +151,24 @@ export class PerflogMetric extends Metric {
|
||||||
events.forEach( (event) => {
|
events.forEach( (event) => {
|
||||||
var ph = event['ph'];
|
var ph = event['ph'];
|
||||||
var name = event['name'];
|
var name = event['name'];
|
||||||
|
var microIterations = 1;
|
||||||
|
var microIterationsMatch = RegExpWrapper.firstMatch(_MICRO_ITERATIONS_REGEX, name);
|
||||||
|
if (isPresent(microIterationsMatch)) {
|
||||||
|
name = microIterationsMatch[1];
|
||||||
|
microIterations = NumberWrapper.parseInt(microIterationsMatch[2], 10);
|
||||||
|
}
|
||||||
|
|
||||||
if (StringWrapper.equals(ph, 'b') && StringWrapper.equals(name, markName)) {
|
if (StringWrapper.equals(ph, 'b') && StringWrapper.equals(name, markName)) {
|
||||||
markStartEvent = event;
|
markStartEvent = event;
|
||||||
} else if (StringWrapper.equals(ph, 'e') && StringWrapper.equals(name, markName)) {
|
} else if (StringWrapper.equals(ph, 'e') && StringWrapper.equals(name, markName)) {
|
||||||
markEndEvent = event;
|
markEndEvent = event;
|
||||||
}
|
}
|
||||||
if (isPresent(markStartEvent) && isBlank(markEndEvent) && event['pid'] === markStartEvent['pid']) {
|
if (isPresent(markStartEvent) && isBlank(markEndEvent) && event['pid'] === markStartEvent['pid']) {
|
||||||
if (StringWrapper.equals(ph, 'B')) {
|
if (StringWrapper.equals(ph, 'B') || StringWrapper.equals(ph, 'b')) {
|
||||||
intervalStarts[name] = event;
|
intervalStarts[name] = event;
|
||||||
} else if (StringWrapper.equals(ph, 'E') && isPresent(intervalStarts[name])) {
|
} else if ((StringWrapper.equals(ph, 'E') || StringWrapper.equals(ph, 'e')) && isPresent(intervalStarts[name])) {
|
||||||
var startEvent = intervalStarts[name];
|
var startEvent = intervalStarts[name];
|
||||||
var duration = event['ts'] - startEvent['ts'];
|
var duration = (event['ts'] - startEvent['ts']);
|
||||||
intervalStarts[name] = null;
|
intervalStarts[name] = null;
|
||||||
if (StringWrapper.equals(name, 'gc')) {
|
if (StringWrapper.equals(name, 'gc')) {
|
||||||
result['gcTime'] += duration;
|
result['gcTime'] += duration;
|
||||||
|
@ -177,14 +188,13 @@ export class PerflogMetric extends Metric {
|
||||||
}
|
}
|
||||||
} else if (StringWrapper.equals(name, 'script')) {
|
} else if (StringWrapper.equals(name, 'script')) {
|
||||||
result['scriptTime'] += duration;
|
result['scriptTime'] += duration;
|
||||||
|
} else if (isPresent(this._microMetrics[name])) {
|
||||||
|
result[name] += duration / microIterations;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
result['pureScriptTime'] = result['scriptTime'] - gcTimeInScript - renderTimeInScript;
|
result['pureScriptTime'] = result['scriptTime'] - gcTimeInScript - renderTimeInScript;
|
||||||
if (this._microIterations > 0) {
|
|
||||||
result['microScriptTimeAvg'] = result['scriptTime'] / this._microIterations;
|
|
||||||
}
|
|
||||||
return isPresent(markStartEvent) && isPresent(markEndEvent) ? result : null;
|
return isPresent(markStartEvent) && isPresent(markEndEvent) ? result : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,15 +203,16 @@ export class PerflogMetric extends Metric {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _MICRO_ITERATIONS_REGEX = RegExpWrapper.create('(.+)\\*(\\d+)$');
|
||||||
|
|
||||||
var _MAX_RETRY_COUNT = 20;
|
var _MAX_RETRY_COUNT = 20;
|
||||||
var _MARK_NAME_PREFIX = 'benchpress';
|
var _MARK_NAME_PREFIX = 'benchpress';
|
||||||
var _SET_TIMEOUT = new OpaqueToken('PerflogMetric.setTimeout');
|
var _SET_TIMEOUT = new OpaqueToken('PerflogMetric.setTimeout');
|
||||||
var _BINDINGS = [
|
var _BINDINGS = [
|
||||||
bind(PerflogMetric).toFactory(
|
bind(PerflogMetric).toFactory(
|
||||||
(driverExtension, setTimeout, microIterations) =>
|
(driverExtension, setTimeout, microMetrics) =>
|
||||||
new PerflogMetric(driverExtension, setTimeout, microIterations),
|
new PerflogMetric(driverExtension, setTimeout, microMetrics),
|
||||||
[WebDriverExtension, _SET_TIMEOUT, Options.MICRO_ITERATIONS]
|
[WebDriverExtension, _SET_TIMEOUT, Options.MICRO_METRICS]
|
||||||
),
|
),
|
||||||
bind(_SET_TIMEOUT).toValue( (fn, millis) => PromiseWrapper.setTimeout(fn, millis) ),
|
bind(_SET_TIMEOUT).toValue( (fn, millis) => PromiseWrapper.setTimeout(fn, millis) )
|
||||||
bind(Options.MICRO_ITERATIONS).toValue(0)
|
|
||||||
];
|
];
|
||||||
|
|
|
@ -34,7 +34,7 @@ export class Runner {
|
||||||
this._defaultBindings = defaultBindings;
|
this._defaultBindings = defaultBindings;
|
||||||
}
|
}
|
||||||
|
|
||||||
sample({id, execute, prepare, microIterations, bindings}):Promise<SampleState> {
|
sample({id, execute, prepare, microMetrics, bindings}):Promise<SampleState> {
|
||||||
var sampleBindings = [
|
var sampleBindings = [
|
||||||
_DEFAULT_BINDINGS,
|
_DEFAULT_BINDINGS,
|
||||||
this._defaultBindings,
|
this._defaultBindings,
|
||||||
|
@ -44,8 +44,8 @@ export class Runner {
|
||||||
if (isPresent(prepare)) {
|
if (isPresent(prepare)) {
|
||||||
ListWrapper.push(sampleBindings, bind(Options.PREPARE).toValue(prepare));
|
ListWrapper.push(sampleBindings, bind(Options.PREPARE).toValue(prepare));
|
||||||
}
|
}
|
||||||
if (isPresent(microIterations)) {
|
if (isPresent(microMetrics)) {
|
||||||
ListWrapper.push(sampleBindings, bind(Options.MICRO_ITERATIONS).toValue(microIterations));
|
ListWrapper.push(sampleBindings, bind(Options.MICRO_METRICS).toValue(microMetrics));
|
||||||
}
|
}
|
||||||
if (isPresent(bindings)) {
|
if (isPresent(bindings)) {
|
||||||
ListWrapper.push(sampleBindings, bindings);
|
ListWrapper.push(sampleBindings, bindings);
|
||||||
|
|
|
@ -11,7 +11,7 @@ import {
|
||||||
xit,
|
xit,
|
||||||
} from 'angular2/test_lib';
|
} from 'angular2/test_lib';
|
||||||
|
|
||||||
import { List, ListWrapper } from 'angular2/src/facade/collection';
|
import { List, ListWrapper, StringMapWrapper } from 'angular2/src/facade/collection';
|
||||||
import { PromiseWrapper, Promise } from 'angular2/src/facade/async';
|
import { PromiseWrapper, Promise } from 'angular2/src/facade/async';
|
||||||
import { isPresent, isBlank } from 'angular2/src/facade/lang';
|
import { isPresent, isBlank } from 'angular2/src/facade/lang';
|
||||||
|
|
||||||
|
@ -27,20 +27,23 @@ export function main() {
|
||||||
var commandLog;
|
var commandLog;
|
||||||
var eventFactory = new TraceEventFactory('timeline', 'pid0');
|
var eventFactory = new TraceEventFactory('timeline', 'pid0');
|
||||||
|
|
||||||
function createMetric(perfLogs, microIterations = 0, perfLogFeatures = null) {
|
function createMetric(perfLogs, microMetrics = null, perfLogFeatures = null) {
|
||||||
commandLog = [];
|
commandLog = [];
|
||||||
if (isBlank(perfLogFeatures)) {
|
if (isBlank(perfLogFeatures)) {
|
||||||
perfLogFeatures = new PerfLogFeatures({render: true, gc: true});
|
perfLogFeatures = new PerfLogFeatures({render: true, gc: true});
|
||||||
}
|
}
|
||||||
|
if (isBlank(microMetrics)) {
|
||||||
|
microMetrics = StringMapWrapper.create();
|
||||||
|
}
|
||||||
var bindings = [
|
var bindings = [
|
||||||
Options.DEFAULT_BINDINGS,
|
Options.DEFAULT_BINDINGS,
|
||||||
PerflogMetric.BINDINGS,
|
PerflogMetric.BINDINGS,
|
||||||
|
bind(Options.MICRO_METRICS).toValue(microMetrics),
|
||||||
bind(PerflogMetric.SET_TIMEOUT).toValue( (fn, millis) => {
|
bind(PerflogMetric.SET_TIMEOUT).toValue( (fn, millis) => {
|
||||||
ListWrapper.push(commandLog, ['setTimeout', millis]);
|
ListWrapper.push(commandLog, ['setTimeout', millis]);
|
||||||
fn();
|
fn();
|
||||||
}),
|
}),
|
||||||
bind(WebDriverExtension).toValue(new MockDriverExtension(perfLogs, commandLog, perfLogFeatures)),
|
bind(WebDriverExtension).toValue(new MockDriverExtension(perfLogs, commandLog, perfLogFeatures))
|
||||||
bind(Options.MICRO_ITERATIONS).toValue(microIterations)
|
|
||||||
];
|
];
|
||||||
return new Injector(bindings).get(PerflogMetric);
|
return new Injector(bindings).get(PerflogMetric);
|
||||||
}
|
}
|
||||||
|
@ -48,12 +51,12 @@ export function main() {
|
||||||
describe('perflog metric', () => {
|
describe('perflog metric', () => {
|
||||||
|
|
||||||
it('should describe itself based on the perfLogFeatrues', () => {
|
it('should describe itself based on the perfLogFeatrues', () => {
|
||||||
expect(createMetric([[]], 0, new PerfLogFeatures()).describe()).toEqual({
|
expect(createMetric([[]], null, new PerfLogFeatures()).describe()).toEqual({
|
||||||
'scriptTime': 'script execution time in ms, including gc and render',
|
'scriptTime': 'script execution time in ms, including gc and render',
|
||||||
'pureScriptTime': 'script execution time in ms, without gc nor render'
|
'pureScriptTime': 'script execution time in ms, without gc nor render'
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(createMetric([[]], 0, new PerfLogFeatures({
|
expect(createMetric([[]], null, new PerfLogFeatures({
|
||||||
render: true,
|
render: true,
|
||||||
gc: false
|
gc: false
|
||||||
})).describe()).toEqual({
|
})).describe()).toEqual({
|
||||||
|
@ -72,6 +75,13 @@ export function main() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should describe itself based on micro metrics', () => {
|
||||||
|
var description = createMetric([[]], {
|
||||||
|
'myMicroMetric': 'someDesc'
|
||||||
|
}).describe();
|
||||||
|
expect(description['myMicroMetric']).toEqual('someDesc');
|
||||||
|
});
|
||||||
|
|
||||||
describe('beginMeasure', () => {
|
describe('beginMeasure', () => {
|
||||||
|
|
||||||
it('should mark the timeline', inject([AsyncTestCompleter], (async) => {
|
it('should mark the timeline', inject([AsyncTestCompleter], (async) => {
|
||||||
|
@ -194,10 +204,10 @@ export function main() {
|
||||||
|
|
||||||
describe('aggregation', () => {
|
describe('aggregation', () => {
|
||||||
|
|
||||||
function aggregate(events, microIterations = 0) {
|
function aggregate(events, microMetrics = null) {
|
||||||
ListWrapper.insert(events, 0, eventFactory.markStart('benchpress0', 0));
|
ListWrapper.insert(events, 0, eventFactory.markStart('benchpress0', 0));
|
||||||
ListWrapper.push(events, eventFactory.markEnd('benchpress0', 10));
|
ListWrapper.push(events, eventFactory.markEnd('benchpress0', 10));
|
||||||
var metric = createMetric([events], microIterations);
|
var metric = createMetric([events], microMetrics);
|
||||||
return metric
|
return metric
|
||||||
.beginMeasure().then( (_) => metric.endMeasure(false) );
|
.beginMeasure().then( (_) => metric.endMeasure(false) );
|
||||||
}
|
}
|
||||||
|
@ -319,25 +329,34 @@ export function main() {
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('microIterations', () => {
|
describe('microMetrics', () => {
|
||||||
|
|
||||||
it('should not report microScriptTimeAvg if microIterations = 0', inject([AsyncTestCompleter], (async) => {
|
it('should report micro metrics', inject([AsyncTestCompleter], (async) => {
|
||||||
aggregate([
|
aggregate([
|
||||||
eventFactory.start('script', 0),
|
eventFactory.markStart('mm1', 0),
|
||||||
eventFactory.end('script', 5)
|
eventFactory.markEnd('mm1', 5),
|
||||||
], 0).then((data) => {
|
], {'mm1': 'micro metric 1'}).then((data) => {
|
||||||
expect(isPresent(data['microScriptTimeAvg'])).toBe(false);
|
expect(data['mm1']).toBe(5.0);
|
||||||
async.done();
|
async.done();
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should report microScriptTimeAvg', inject([AsyncTestCompleter], (async) => {
|
it('should ignore micro metrics that were not specified', inject([AsyncTestCompleter], (async) => {
|
||||||
aggregate([
|
aggregate([
|
||||||
eventFactory.start('script', 0),
|
eventFactory.markStart('mm1', 0),
|
||||||
eventFactory.end('script', 5)
|
eventFactory.markEnd('mm1', 5),
|
||||||
], 4).then((data) => {
|
]).then((data) => {
|
||||||
expect(data['scriptTime']).toBe(5);
|
expect(data['mm1']).toBeFalsy();
|
||||||
expect(data['microScriptTimeAvg']).toBe(5/4);
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should report micro metric averages', inject([AsyncTestCompleter], (async) => {
|
||||||
|
aggregate([
|
||||||
|
eventFactory.markStart('mm1*20', 0),
|
||||||
|
eventFactory.markEnd('mm1*20', 5),
|
||||||
|
], {'mm1': 'micro metric 1'}).then((data) => {
|
||||||
|
expect(data['mm1']).toBe(5/20);
|
||||||
async.done();
|
async.done();
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -96,9 +96,9 @@ export function main() {
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should bind Options.MICRO_ITERATIONS', inject([AsyncTestCompleter], (async) => {
|
it('should bind Options.MICRO_METRICS', inject([AsyncTestCompleter], (async) => {
|
||||||
createRunner().sample({id: 'someId', microIterations: 23}).then( (_) => {
|
createRunner().sample({id: 'someId', microMetrics: {'a': 'b'}}).then( (_) => {
|
||||||
expect(injector.get(Options.MICRO_ITERATIONS)).toEqual(23);
|
expect(injector.get(Options.MICRO_METRICS)).toEqual({'a': 'b'});
|
||||||
async.done();
|
async.done();
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
Loading…
Reference in New Issue