refactor(bench press): wrap measure values into an object with time and iteration number.

Closes #689
This commit is contained in:
Tobias Bosch
2015-02-17 14:30:24 -08:00
committed by Misko Hevery
parent e163eb2a51
commit 5e798c632b
11 changed files with 106 additions and 52 deletions
+13
View File
@@ -0,0 +1,13 @@
import { Date } from 'angular2/src/facade/lang';
export class MeasureValues {
timeStamp:Date;
runIndex:number;
values:any;
constructor(runIndex:number, timeStamp:Date, values:any) {
this.timeStamp = timeStamp;
this.runIndex = runIndex;
this.values = values;
}
}
+4 -2
View File
@@ -5,16 +5,18 @@ import {
ABSTRACT, BaseException
} from 'angular2/src/facade/lang';
import { MeasureValues } from './measure_values';
/**
* A reporter reports measure values and the valid sample.
*/
@ABSTRACT()
export class Reporter {
reportMeasureValues(index:number, values:any):Promise {
reportMeasureValues(values:MeasureValues):Promise {
throw new BaseException('NYI');
}
reportSample(completeSample:List, validSample:List):Promise {
reportSample(completeSample:List<MeasureValues>, validSample:List<MeasureValues>):Promise {
throw new BaseException('NYI');
}
}
@@ -7,6 +7,7 @@ import { bind, OpaqueToken } from 'angular2/di';
import { Statistic } from '../statistic';
import { Reporter } from '../reporter';
import { SampleDescription } from '../sample_description';
import { MeasureValues } from '../measure_values';
/**
* A reporter for the console
@@ -72,20 +73,20 @@ export class ConsoleReporter extends Reporter {
this._printStringRow(this._metricNames.map( (_) => '' ), '-');
}
reportMeasureValues(index:number, measuredValues:any):Promise {
reportMeasureValues(measureValues:MeasureValues):Promise {
var formattedValues = ListWrapper.map(this._metricNames, (metricName) => {
var value = measuredValues[metricName];
var value = measureValues.values[metricName];
return ConsoleReporter._formatNum(value);
});
this._printStringRow(formattedValues);
return PromiseWrapper.resolve(null);
}
reportSample(completeSample:List, validSample:List):Promise {
reportSample(completeSample:List<MeasureValues>, validSample:List<MeasureValues>):Promise {
this._printStringRow(this._metricNames.map( (_) => '' ), '=');
this._printStringRow(
ListWrapper.map(this._metricNames, (metricName) => {
var sample = ListWrapper.map(validSample, (measuredValues) => measuredValues[metricName]);
var sample = ListWrapper.map(validSample, (measureValues) => measureValues.values[metricName]);
var mean = Statistic.calculateMean(sample);
var cv = Statistic.calculateCoefficientOfVariation(sample, mean);
return `${ConsoleReporter._formatNum(mean)}\u00B1${Math.floor(cv)}%`;
+20 -10
View File
@@ -1,4 +1,4 @@
import { isPresent, isBlank } from 'angular2/src/facade/lang';
import { isPresent, isBlank, Date, DateWrapper } from 'angular2/src/facade/lang';
import { Promise, PromiseWrapper } from 'angular2/src/facade/async';
import { StringMapWrapper, List, ListWrapper } from 'angular2/src/facade/collection';
import { bind, OpaqueToken } from 'angular2/di';
@@ -10,6 +10,7 @@ import { WebDriverExtension } from './web_driver_extension';
import { WebDriverAdapter } from './web_driver_adapter';
import { Options } from './sample_options';
import { MeasureValues} from './measure_values';
/**
* The Sampler owns the sample loop:
@@ -22,6 +23,8 @@ import { Options } from './sample_options';
export class Sampler {
// TODO(tbosch): use static values when our transpiler supports them
static get BINDINGS() { return _BINDINGS; }
// TODO(tbosch): use static values when our transpiler supports them
static get TIME() { return _TIME; }
_driver:WebDriverAdapter;
_driverExtension:WebDriverExtension;
@@ -31,13 +34,14 @@ export class Sampler {
_forceGc:boolean;
_prepare:Function;
_execute:Function;
_time:Function;
constructor({
driver, driverExtension, metric, reporter, validator, forceGc, prepare, execute
driver, driverExtension, metric, reporter, validator, forceGc, prepare, execute, time
}:{
driver: WebDriverAdapter,
driverExtension: WebDriverExtension, metric: Metric, reporter: Reporter,
validator: Validator, prepare: Function, execute: Function
validator: Validator, prepare: Function, execute: Function, time: Function
}={}) {
this._driver = driver;
this._driverExtension = driverExtension;
@@ -47,6 +51,7 @@ export class Sampler {
this._forceGc = forceGc;
this._prepare = prepare;
this._execute = execute;
this._time = time;
}
sample():Promise<SampleState> {
@@ -90,10 +95,11 @@ export class Sampler {
.then( (measureValues) => this._report(lastState, measureValues) );
}
_report(state:SampleState, measuredValues:any):Promise<SampleState> {
var completeSample = ListWrapper.concat(state.completeSample, [measuredValues]);
_report(state:SampleState, metricValues:any):Promise<SampleState> {
var measureValues = new MeasureValues(state.completeSample.length, this._time(), metricValues);
var completeSample = ListWrapper.concat(state.completeSample, [measureValues]);
var validSample = this._validator.validate(completeSample);
var resultPromise = this._reporter.reportMeasureValues(completeSample.length - 1, measuredValues);
var resultPromise = this._reporter.reportMeasureValues(measureValues);
if (isPresent(validSample)) {
resultPromise = resultPromise.then( (_) => this._reporter.reportSample(completeSample, validSample) )
}
@@ -112,9 +118,11 @@ export class SampleState {
}
}
var _TIME = new OpaqueToken('Sampler.time');
var _BINDINGS = [
bind(Sampler).toFactory(
(driver, driverExtension, metric, reporter, validator, forceGc, prepare, execute) => new Sampler({
(driver, driverExtension, metric, reporter, validator, forceGc, prepare, execute, time) => new Sampler({
driver: driver,
driverExtension: driverExtension,
reporter: reporter,
@@ -125,10 +133,12 @@ var _BINDINGS = [
// Mostly because the cache would have to be initialized with a
// special null object, which is expensive.
prepare: prepare !== false ? prepare : null,
execute: execute
execute: execute,
time: time
}),
[WebDriverAdapter, WebDriverExtension, Metric, Reporter, Validator, Options.FORCE_GC, Options.PREPARE, Options.EXECUTE]
[WebDriverAdapter, WebDriverExtension, Metric, Reporter, Validator, Options.FORCE_GC, Options.PREPARE, Options.EXECUTE, _TIME]
),
bind(Options.FORCE_GC).toValue(false),
bind(Options.PREPARE).toValue(false)
bind(Options.PREPARE).toValue(false),
bind(_TIME).toValue( () => DateWrapper.now() )
];
+3 -1
View File
@@ -3,6 +3,8 @@ import {
ABSTRACT, BaseException
} from 'angular2/src/facade/lang';
import { MeasureValues } from './measure_values';
/**
* A Validator calculates a valid sample out of the complete sample.
* A valid sample is a sample that represents the population that should be observed
@@ -13,7 +15,7 @@ export class Validator {
/**
* Calculates a valid sample out of the complete sample
*/
validate(completeSample:List<any>):List<any> {
validate(completeSample:List<MeasureValues>):List<MeasureValues> {
throw new BaseException('NYI');
}
@@ -3,6 +3,7 @@ import { bind, OpaqueToken } from 'angular2/di';
import { Validator } from '../validator';
import { Statistic } from '../statistic';
import { MeasureValues } from '../measure_values';
/**
* A validator that checks the regression slope of a specific metric.
@@ -32,7 +33,7 @@ export class RegressionSlopeValidator extends Validator {
};
}
validate(completeSample:List<any>):List<any> {
validate(completeSample:List<MeasureValues>):List<MeasureValues> {
if (completeSample.length >= this._sampleSize) {
var latestSample =
ListWrapper.slice(completeSample, completeSample.length - this._sampleSize, completeSample.length);
@@ -42,7 +43,7 @@ export class RegressionSlopeValidator extends Validator {
// For now, we only use the array index as x value.
// TODO(tbosch): think about whether we should use time here instead
ListWrapper.push(xValues, i);
ListWrapper.push(yValues, latestSample[i][this._metric]);
ListWrapper.push(yValues, latestSample[i].values[this._metric]);
}
var regressionSlope = Statistic.calculateRegressionSlope(
xValues, Statistic.calculateMean(xValues),