feat(bench press): add microIterations option
This commit is contained in:
parent
03793d0714
commit
043b8c6d2e
|
@ -23,7 +23,14 @@ 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 = [];
|
||||||
config.params.forEach(function(param) {
|
var microIterations = config.microIterations || 0;
|
||||||
|
var params = config.params || [];
|
||||||
|
if (microIterations) {
|
||||||
|
params = params.concat([{
|
||||||
|
name: 'iterations', value: microIterations, scale: 'linear'
|
||||||
|
}]);
|
||||||
|
}
|
||||||
|
params.forEach(function(param) {
|
||||||
var name = param.name;
|
var name = param.name;
|
||||||
var value = applyScaleFactor(param.value, scaleFactor, param.scale);
|
var value = applyScaleFactor(param.value, scaleFactor, param.scale);
|
||||||
urlParams.push(name + '=' + value);
|
urlParams.push(name + '=' + value);
|
||||||
|
@ -35,6 +42,7 @@ function runBenchmark(config) {
|
||||||
id: config.id,
|
id: config.id,
|
||||||
execute: config.work,
|
execute: config.work,
|
||||||
prepare: config.prepare,
|
prepare: config.prepare,
|
||||||
|
microIterations: microIterations,
|
||||||
bindings: [
|
bindings: [
|
||||||
benchpress.bind(benchpress.Options.SAMPLE_DESCRIPTION).toValue(description)
|
benchpress.bind(benchpress.Options.SAMPLE_DESCRIPTION).toValue(description)
|
||||||
]
|
]
|
||||||
|
|
|
@ -12,8 +12,9 @@ describe('ng2 change detection benchmark', function () {
|
||||||
buttons: ['#ng2ChangeDetectionDynamic'],
|
buttons: ['#ng2ChangeDetectionDynamic'],
|
||||||
id: 'ng2.changeDetection.dynamic',
|
id: 'ng2.changeDetection.dynamic',
|
||||||
params: [{
|
params: [{
|
||||||
name: 'numberOfChecks', value: 900000, scale: 'linear'
|
name: 'numberOfChecks', value: 900000
|
||||||
}]
|
}],
|
||||||
|
microIterations: 20
|
||||||
}).then(done, done.fail);
|
}).then(done, done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -23,8 +24,9 @@ describe('ng2 change detection benchmark', function () {
|
||||||
buttons: ['#ng2ChangeDetectionJit'],
|
buttons: ['#ng2ChangeDetectionJit'],
|
||||||
id: 'ng2.changeDetection.jit',
|
id: 'ng2.changeDetection.jit',
|
||||||
params: [{
|
params: [{
|
||||||
name: 'numberOfChecks', value: 900000, scale: 'linear'
|
name: 'numberOfChecks', value: 900000
|
||||||
}]
|
}],
|
||||||
|
microIterations: 20
|
||||||
}).then(done, done.fail);
|
}).then(done, done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -34,8 +36,9 @@ describe('ng2 change detection benchmark', function () {
|
||||||
buttons: ['#baselineChangeDetection'],
|
buttons: ['#baselineChangeDetection'],
|
||||||
id: 'baseline.changeDetection',
|
id: 'baseline.changeDetection',
|
||||||
params: [{
|
params: [{
|
||||||
name: 'numberOfChecks', value: 900000, scale: 'linear'
|
name: 'numberOfChecks', value: 900000
|
||||||
}]
|
}],
|
||||||
|
microIterations: 20
|
||||||
}).then(done, done.fail);
|
}).then(done, done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,8 @@ describe('ng2 di benchmark', function () {
|
||||||
id: 'ng2.di.getByToken',
|
id: 'ng2.di.getByToken',
|
||||||
params: [{
|
params: [{
|
||||||
name: 'iterations', value: 20000, scale: 'linear'
|
name: 'iterations', value: 20000, scale: 'linear'
|
||||||
}]
|
}],
|
||||||
|
microIterations: 20000
|
||||||
}).then(done, done.fail);
|
}).then(done, done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -22,9 +23,7 @@ describe('ng2 di benchmark', function () {
|
||||||
url: URL,
|
url: URL,
|
||||||
buttons: ['#getByKey'],
|
buttons: ['#getByKey'],
|
||||||
id: 'ng2.di.getByKey',
|
id: 'ng2.di.getByKey',
|
||||||
params: [{
|
microIterations: 20000
|
||||||
name: 'iterations', value: 20000, scale: 'linear'
|
|
||||||
}]
|
|
||||||
}).then(done, done.fail);
|
}).then(done, done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -33,9 +32,7 @@ describe('ng2 di benchmark', function () {
|
||||||
url: URL,
|
url: URL,
|
||||||
buttons: ['#getChild'],
|
buttons: ['#getChild'],
|
||||||
id: 'ng2.di.getChild',
|
id: 'ng2.di.getChild',
|
||||||
params: [{
|
microIterations: 20000
|
||||||
name: 'iterations', value: 20000, scale: 'linear'
|
|
||||||
}]
|
|
||||||
}).then(done, done.fail);
|
}).then(done, done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -44,9 +41,7 @@ describe('ng2 di benchmark', function () {
|
||||||
url: URL,
|
url: URL,
|
||||||
buttons: ['#instantiate'],
|
buttons: ['#instantiate'],
|
||||||
id: 'ng2.di.instantiate',
|
id: 'ng2.di.instantiate',
|
||||||
params: [{
|
microIterations: 10000
|
||||||
name: 'iterations', value: 10000, scale: 'linear'
|
|
||||||
}]
|
|
||||||
}).then(done, done.fail);
|
}).then(done, done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,7 @@ describe('ng2 element injector benchmark', function () {
|
||||||
url: URL,
|
url: URL,
|
||||||
buttons: ['#instantiate'],
|
buttons: ['#instantiate'],
|
||||||
id: 'ng2.elementInjector.instantiate',
|
id: 'ng2.elementInjector.instantiate',
|
||||||
params: [{
|
microIterations: 20000
|
||||||
name: 'iterations', value: 20000, scale: 'linear'
|
|
||||||
}]
|
|
||||||
}).then(done, done.fail);
|
}).then(done, done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -22,9 +20,7 @@ describe('ng2 element injector benchmark', function () {
|
||||||
url: URL,
|
url: URL,
|
||||||
buttons: ['#instantiateDirectives'],
|
buttons: ['#instantiateDirectives'],
|
||||||
id: 'ng2.elementInjector.instantiateDirectives',
|
id: 'ng2.elementInjector.instantiateDirectives',
|
||||||
params: [{
|
microIterations: 20000
|
||||||
name: 'iterations', value: 20000, scale: 'linear'
|
|
||||||
}]
|
|
||||||
}).then(done, done.fail);
|
}).then(done, done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
<h2>Params</h2>
|
<h2>Params</h2>
|
||||||
<form>
|
<form>
|
||||||
Iterations:
|
Iterations:
|
||||||
|
<input type="number" name="iterations" placeholder="iterations" value="20">
|
||||||
|
Number of checks:
|
||||||
<input type="number" name="numberOfChecks" placeholder="numberOfChecks" value="900000">
|
<input type="number" name="numberOfChecks" placeholder="numberOfChecks" value="900000">
|
||||||
<br>
|
<br>
|
||||||
<button>Apply</button>
|
<button>Apply</button>
|
||||||
|
|
|
@ -138,9 +138,9 @@ function setUpChangeDetection(changeDetection:ChangeDetection, iterations) {
|
||||||
export function main () {
|
export function main () {
|
||||||
BrowserDomAdapter.makeCurrent();
|
BrowserDomAdapter.makeCurrent();
|
||||||
var numberOfChecks = getIntParameter('numberOfChecks');
|
var numberOfChecks = getIntParameter('numberOfChecks');
|
||||||
|
var numberOfRuns = getIntParameter('iterations');
|
||||||
|
|
||||||
var numberOfChecksPerDetector = 10;
|
var numberOfChecksPerDetector = 10;
|
||||||
var numberOfRuns = 20;
|
|
||||||
var numberOfDetectors = numberOfChecks / numberOfChecksPerDetector / numberOfRuns;
|
var numberOfDetectors = numberOfChecks / numberOfChecksPerDetector / numberOfRuns;
|
||||||
|
|
||||||
setUpReflector();
|
setUpReflector();
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { bind, OpaqueToken } from 'angular2/di';
|
||||||
|
|
||||||
import { WebDriverExtension } from '../web_driver_extension';
|
import { WebDriverExtension } from '../web_driver_extension';
|
||||||
import { Metric } from '../metric';
|
import { Metric } from '../metric';
|
||||||
|
import { Options } from '../sample_options';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A metric that reads out the performance log
|
* A metric that reads out the performance log
|
||||||
|
@ -19,17 +20,25 @@ export class PerflogMetric extends Metric {
|
||||||
_remainingEvents:List;
|
_remainingEvents:List;
|
||||||
_measureCount:int;
|
_measureCount:int;
|
||||||
_setTimeout:Function;
|
_setTimeout:Function;
|
||||||
|
_microIterations:int;
|
||||||
|
|
||||||
constructor(driverExtension:WebDriverExtension, setTimeout:Function) {
|
/**
|
||||||
|
* @param driverExtension
|
||||||
|
* @param setTimeout
|
||||||
|
* @param microIterations Number of iterations that run inside the browser by user code.
|
||||||
|
* Used for micro benchmarks.
|
||||||
|
**/
|
||||||
|
constructor(driverExtension:WebDriverExtension, setTimeout:Function, microIterations:int) {
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
describe():StringMap {
|
describe():StringMap {
|
||||||
return {
|
var res = {
|
||||||
'script': 'script execution time in ms',
|
'script': 'script execution time in ms',
|
||||||
'render': 'render time in ms',
|
'render': 'render time in ms',
|
||||||
'gcTime': 'gc time in ms',
|
'gcTime': 'gc time in ms',
|
||||||
|
@ -37,6 +46,10 @@ export class PerflogMetric extends Metric {
|
||||||
'gcTimeInScript': 'gc time during script execution in ms',
|
'gcTimeInScript': 'gc time during script execution in ms',
|
||||||
'gcAmountInScript': 'gc amount during script execution in kbytes'
|
'gcAmountInScript': 'gc amount during script execution in kbytes'
|
||||||
};
|
};
|
||||||
|
if (this._microIterations > 0) {
|
||||||
|
res['scriptMicroAvg'] = 'average script time for a micro iteration';
|
||||||
|
}
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
beginMeasure():Promise {
|
beginMeasure():Promise {
|
||||||
|
@ -148,6 +161,9 @@ export class PerflogMetric extends Metric {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
result['script'] -= result['gcTimeInScript'];
|
result['script'] -= result['gcTimeInScript'];
|
||||||
|
if (this._microIterations > 0) {
|
||||||
|
result['scriptMicroAvg'] = result['script'] / this._microIterations;
|
||||||
|
}
|
||||||
return isPresent(markStartEvent) && isPresent(markEndEvent) ? result : null;
|
return isPresent(markStartEvent) && isPresent(markEndEvent) ? result : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,8 +177,9 @@ 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) => new PerflogMetric(driverExtension, setTimeout),
|
(driverExtension, setTimeout, microIterations) => new PerflogMetric(driverExtension, setTimeout, microIterations),
|
||||||
[WebDriverExtension, _SET_TIMEOUT]
|
[WebDriverExtension, _SET_TIMEOUT, Options.MICRO_ITERATIONS]
|
||||||
),
|
),
|
||||||
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, bindings}):Promise<SampleState> {
|
sample({id, execute, prepare, microIterations, bindings}):Promise<SampleState> {
|
||||||
var sampleBindings = [
|
var sampleBindings = [
|
||||||
_DEFAULT_BINDINGS,
|
_DEFAULT_BINDINGS,
|
||||||
this._defaultBindings,
|
this._defaultBindings,
|
||||||
|
@ -44,6 +44,9 @@ 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)) {
|
||||||
|
ListWrapper.push(sampleBindings, bind(Options.MICRO_ITERATIONS).toValue(microIterations));
|
||||||
|
}
|
||||||
if (isPresent(bindings)) {
|
if (isPresent(bindings)) {
|
||||||
ListWrapper.push(sampleBindings, bindings);
|
ListWrapper.push(sampleBindings, bindings);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,12 @@ export class Options {
|
||||||
static get CAPABILITIES() { return _CAPABILITIES; }
|
static get CAPABILITIES() { return _CAPABILITIES; }
|
||||||
// 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
|
||||||
|
/**
|
||||||
|
* Number of iterations that run inside the browser by user code.
|
||||||
|
* Used for micro benchmarks.
|
||||||
|
**/
|
||||||
|
static get MICRO_ITERATIONS() { return _MICRO_ITERATIONS; }
|
||||||
}
|
}
|
||||||
|
|
||||||
var _SAMPLE_ID = new OpaqueToken('Options.sampleId');
|
var _SAMPLE_ID = new OpaqueToken('Options.sampleId');
|
||||||
|
@ -27,3 +33,4 @@ 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');
|
||||||
|
|
|
@ -136,7 +136,10 @@ var _BINDINGS = [
|
||||||
execute: execute,
|
execute: execute,
|
||||||
time: time
|
time: time
|
||||||
}),
|
}),
|
||||||
[WebDriverAdapter, WebDriverExtension, Metric, Reporter, Validator, Options.FORCE_GC, Options.PREPARE, Options.EXECUTE, _TIME]
|
[
|
||||||
|
WebDriverAdapter, WebDriverExtension, Metric, Reporter, Validator,
|
||||||
|
Options.FORCE_GC, Options.PREPARE, Options.EXECUTE, _TIME
|
||||||
|
]
|
||||||
),
|
),
|
||||||
bind(Options.FORCE_GC).toValue(false),
|
bind(Options.FORCE_GC).toValue(false),
|
||||||
bind(Options.PREPARE).toValue(false),
|
bind(Options.PREPARE).toValue(false),
|
||||||
|
|
|
@ -2,8 +2,9 @@ import {ddescribe, describe, it, iit, xit, expect, beforeEach, afterEach} from '
|
||||||
|
|
||||||
import { List, ListWrapper } from 'angular2/src/facade/collection';
|
import { List, ListWrapper } from 'angular2/src/facade/collection';
|
||||||
import { PromiseWrapper, Promise } from 'angular2/src/facade/async';
|
import { PromiseWrapper, Promise } from 'angular2/src/facade/async';
|
||||||
|
import { isPresent } from 'angular2/src/facade/lang';
|
||||||
|
|
||||||
import { Metric, PerflogMetric, WebDriverExtension, bind, Injector } from 'benchpress/common';
|
import { Metric, PerflogMetric, WebDriverExtension, bind, Injector, Options } from 'benchpress/common';
|
||||||
|
|
||||||
import { TraceEventFactory } from '../trace_event_factory';
|
import { TraceEventFactory } from '../trace_event_factory';
|
||||||
|
|
||||||
|
@ -11,16 +12,18 @@ export function main() {
|
||||||
var commandLog;
|
var commandLog;
|
||||||
var eventFactory = new TraceEventFactory('timeline', 'pid0');
|
var eventFactory = new TraceEventFactory('timeline', 'pid0');
|
||||||
|
|
||||||
function createMetric(perfLogs) {
|
function createMetric(perfLogs, microIterations = 0) {
|
||||||
commandLog = [];
|
commandLog = [];
|
||||||
return new Injector([
|
var bindings = [
|
||||||
PerflogMetric.BINDINGS,
|
PerflogMetric.BINDINGS,
|
||||||
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))
|
bind(WebDriverExtension).toValue(new MockDriverExtension(perfLogs, commandLog)),
|
||||||
]).get(PerflogMetric);
|
bind(Options.MICRO_ITERATIONS).toValue(microIterations)
|
||||||
|
];
|
||||||
|
return new Injector(bindings).get(PerflogMetric);
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('perflog metric', () => {
|
describe('perflog metric', () => {
|
||||||
|
@ -151,10 +154,10 @@ export function main() {
|
||||||
|
|
||||||
describe('aggregation', () => {
|
describe('aggregation', () => {
|
||||||
|
|
||||||
function aggregate(events) {
|
function aggregate(events, microIterations = 0) {
|
||||||
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]);
|
var metric = createMetric([events], microIterations);
|
||||||
return metric
|
return metric
|
||||||
.beginMeasure().then( (_) => metric.endMeasure(false) );
|
.beginMeasure().then( (_) => metric.endMeasure(false) );
|
||||||
}
|
}
|
||||||
|
@ -252,6 +255,31 @@ export function main() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('microIterations', () => {
|
||||||
|
|
||||||
|
it('should not report scriptMicroAvg if microIterations = 0', (done) => {
|
||||||
|
aggregate([
|
||||||
|
eventFactory.start('script', 0),
|
||||||
|
eventFactory.end('script', 5)
|
||||||
|
], 0).then((data) => {
|
||||||
|
expect(isPresent(data['scriptMicroAvg'])).toBe(false);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should report scriptMicroAvg', (done) => {
|
||||||
|
aggregate([
|
||||||
|
eventFactory.start('script', 0),
|
||||||
|
eventFactory.end('script', 5)
|
||||||
|
], 4).then((data) => {
|
||||||
|
expect(data['script']).toBe(5);
|
||||||
|
expect(data['scriptMicroAvg']).toBe(5/4);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
describe('gcTimeInScript / gcAmountInScript', () => {
|
describe('gcTimeInScript / gcAmountInScript', () => {
|
||||||
|
|
||||||
it('should detect gc during script execution with begin/end events', (done) => {
|
it('should detect gc during script execution with begin/end events', (done) => {
|
||||||
|
|
|
@ -85,6 +85,13 @@ export function main() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should bind Options.MICRO_ITERATIONS', (done) => {
|
||||||
|
createRunner().sample({id: 'someId', microIterations: 23}).then( (_) => {
|
||||||
|
expect(injector.get(Options.MICRO_ITERATIONS)).toEqual(23);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should overwrite bindings per sample call', (done) => {
|
it('should overwrite bindings per sample call', (done) => {
|
||||||
createRunner([
|
createRunner([
|
||||||
bind(Options.DEFAULT_DESCRIPTION).toValue({'a': 1}),
|
bind(Options.DEFAULT_DESCRIPTION).toValue({'a': 1}),
|
||||||
|
|
Loading…
Reference in New Issue