feat(benchpress): also report the statistics in the generated file

This commit is contained in:
Tobias Bosch 2016-08-30 09:55:14 -07:00
parent 942104d9ac
commit 873233e825
4 changed files with 54 additions and 26 deletions

View File

@ -14,7 +14,8 @@ import {Math} from '../facade/math';
import {MeasureValues} from '../measure_values'; import {MeasureValues} from '../measure_values';
import {Reporter} from '../reporter'; import {Reporter} from '../reporter';
import {SampleDescription} from '../sample_description'; import {SampleDescription} from '../sample_description';
import {Statistic} from '../statistic';
import {formatNum, formatStats, sortedProps} from './util';
/** /**
@ -37,15 +38,6 @@ export class ConsoleReporter extends Reporter {
return result + value; return result + value;
} }
private static _formatNum(n: number) { return NumberWrapper.toFixed(n, 2); }
private static _sortedProps(obj: {[key: string]: any}) {
var props: string[] = [];
StringMapWrapper.forEach(obj, (value, prop) => props.push(prop));
props.sort();
return props;
}
private _metricNames: string[]; private _metricNames: string[];
constructor( constructor(
@ -53,14 +45,14 @@ export class ConsoleReporter extends Reporter {
sampleDescription: SampleDescription, sampleDescription: SampleDescription,
@Inject(ConsoleReporter.PRINT) private _print: Function) { @Inject(ConsoleReporter.PRINT) private _print: Function) {
super(); super();
this._metricNames = ConsoleReporter._sortedProps(sampleDescription.metrics); this._metricNames = sortedProps(sampleDescription.metrics);
this._printDescription(sampleDescription); this._printDescription(sampleDescription);
} }
private _printDescription(sampleDescription: SampleDescription) { private _printDescription(sampleDescription: SampleDescription) {
this._print(`BENCHMARK ${sampleDescription.id}`); this._print(`BENCHMARK ${sampleDescription.id}`);
this._print('Description:'); this._print('Description:');
var props = ConsoleReporter._sortedProps(sampleDescription.description); var props = sortedProps(sampleDescription.description);
props.forEach((prop) => { this._print(`- ${prop}: ${sampleDescription.description[prop]}`); }); props.forEach((prop) => { this._print(`- ${prop}: ${sampleDescription.description[prop]}`); });
this._print('Metrics:'); this._print('Metrics:');
this._metricNames.forEach((metricName) => { this._metricNames.forEach((metricName) => {
@ -74,7 +66,7 @@ export class ConsoleReporter extends Reporter {
reportMeasureValues(measureValues: MeasureValues): Promise<any> { reportMeasureValues(measureValues: MeasureValues): Promise<any> {
var formattedValues = this._metricNames.map(metricName => { var formattedValues = this._metricNames.map(metricName => {
var value = measureValues.values[metricName]; var value = measureValues.values[metricName];
return ConsoleReporter._formatNum(value); return formatNum(value);
}); });
this._printStringRow(formattedValues); this._printStringRow(formattedValues);
return Promise.resolve(null); return Promise.resolve(null);
@ -82,15 +74,8 @@ export class ConsoleReporter extends Reporter {
reportSample(completeSample: MeasureValues[], validSamples: MeasureValues[]): Promise<any> { reportSample(completeSample: MeasureValues[], validSamples: MeasureValues[]): Promise<any> {
this._printStringRow(this._metricNames.map((_) => ''), '='); this._printStringRow(this._metricNames.map((_) => ''), '=');
this._printStringRow(this._metricNames.map(metricName => { this._printStringRow(
var samples = validSamples.map(measureValues => measureValues.values[metricName]); this._metricNames.map(metricName => formatStats(validSamples, metricName)));
var mean = Statistic.calculateMean(samples);
var cv = Statistic.calculateCoefficientOfVariation(samples, mean);
var formattedMean = ConsoleReporter._formatNum(mean);
// Note: Don't use the unicode character for +- as it might cause
// hickups for consoles...
return NumberWrapper.isNaN(cv) ? formattedMean : `${formattedMean}+-${Math.floor(cv)}%`;
}));
return Promise.resolve(null); return Promise.resolve(null);
} }

View File

@ -14,6 +14,7 @@ import {MeasureValues} from '../measure_values';
import {Reporter} from '../reporter'; import {Reporter} from '../reporter';
import {SampleDescription} from '../sample_description'; import {SampleDescription} from '../sample_description';
import {formatStats, sortedProps} from './util';
/** /**
@ -34,10 +35,15 @@ export class JsonFileReporter extends Reporter {
reportMeasureValues(measureValues: MeasureValues): Promise<any> { return Promise.resolve(null); } reportMeasureValues(measureValues: MeasureValues): Promise<any> { return Promise.resolve(null); }
reportSample(completeSample: MeasureValues[], validSample: MeasureValues[]): Promise<any> { reportSample(completeSample: MeasureValues[], validSample: MeasureValues[]): Promise<any> {
const stats: {[key: string]: string} = {};
sortedProps(this._description.metrics).forEach((metricName) => {
stats[metricName] = formatStats(validSample, metricName);
});
var content = Json.stringify({ var content = Json.stringify({
'description': this._description, 'description': this._description,
'stats': stats,
'completeSample': completeSample, 'completeSample': completeSample,
'validSample': validSample 'validSample': validSample,
}); });
var filePath = var filePath =
`${this._path}/${this._description.id}_${DateWrapper.toMillis(this._now())}.json`; `${this._path}/${this._description.id}_${DateWrapper.toMillis(this._now())}.json`;

View File

@ -0,0 +1,33 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {StringMapWrapper} from '../facade/collection';
import {NumberWrapper} from '../facade/lang';
import {MeasureValues} from '../measure_values';
import {Statistic} from '../statistic';
export function formatNum(n: number) {
return NumberWrapper.toFixed(n, 2);
}
export function sortedProps(obj: {[key: string]: any}) {
var props: string[] = [];
StringMapWrapper.forEach(obj, (value, prop) => props.push(prop));
props.sort();
return props;
}
export function formatStats(validSamples: MeasureValues[], metricName: string): string {
var samples = validSamples.map(measureValues => measureValues.values[metricName]);
var mean = Statistic.calculateMean(samples);
var cv = Statistic.calculateCoefficientOfVariation(samples, mean);
var formattedMean = formatNum(mean);
// Note: Don't use the unicode character for +- as it might cause
// hickups for consoles...
return NumberWrapper.isNaN(cv) ? formattedMean : `${formattedMean}+-${Math.floor(cv)}%`;
}

View File

@ -44,7 +44,7 @@ export function main() {
sampleId: 'someId', sampleId: 'someId',
descriptions: [{'a': 2}], descriptions: [{'a': 2}],
path: 'somePath', path: 'somePath',
metrics: {'script': 'script time'} metrics: {'a': 'script time', 'b': 'render time'}
}) })
.reportSample( .reportSample(
[mv(0, 0, {'a': 3, 'b': 6})], [mv(0, 0, {'a': 3, 'b': 6})],
@ -53,8 +53,12 @@ export function main() {
expect(isPresent(loggedFile['filename'].match(regExp))).toBe(true); expect(isPresent(loggedFile['filename'].match(regExp))).toBe(true);
var parsedContent = Json.parse(loggedFile['content']); var parsedContent = Json.parse(loggedFile['content']);
expect(parsedContent).toEqual({ expect(parsedContent).toEqual({
'description': 'description': {
{'id': 'someId', 'description': {'a': 2}, 'metrics': {'script': 'script time'}}, 'id': 'someId',
'description': {'a': 2},
'metrics': {'a': 'script time', 'b': 'render time'}
},
'stats': {'a': '4.00+-25%', 'b': '7.50+-20%'},
'completeSample': [ 'completeSample': [
{'timeStamp': '1970-01-01T00:00:00.000Z', 'runIndex': 0, 'values': {'a': 3, 'b': 6}} {'timeStamp': '1970-01-01T00:00:00.000Z', 'runIndex': 0, 'values': {'a': 3, 'b': 6}}
], ],