From ea9adc04734c8a57b90a773c3d808070470b066b Mon Sep 17 00:00:00 2001 From: Diego Ferreiro Val Date: Thu, 20 Jun 2019 10:03:38 -0700 Subject: [PATCH] fix: stats --- packages/@best/analyzer/src/index.ts | 11 +++-- packages/@best/cli/src/cli/index.ts | 2 +- packages/@best/cli/src/cli/output.ts | 64 ++++++++-------------------- packages/@best/types/src/stats.ts | 10 +++-- 4 files changed, 32 insertions(+), 55 deletions(-) diff --git a/packages/@best/analyzer/src/index.ts b/packages/@best/analyzer/src/index.ts index 267a0553..6f7729bd 100644 --- a/packages/@best/analyzer/src/index.ts +++ b/packages/@best/analyzer/src/index.ts @@ -1,5 +1,5 @@ import { VERSION } from './constants'; -import { BenchmarkResultsSnapshot, BenchmarkResultNode, BenchmarkMetricNames, BenchmarkStats, AllBenchmarksMetricsMap, BenchmarkMetricsAggregate, AllBenchmarkMetricStatsMap, StatsNode, BenchmarkMetricStatsMap, StatsNodeGroup } from "@best/types"; +import { BenchmarkResultsSnapshot, BenchmarkResultNode, BenchmarkMetricNames, BenchmarkStats, AllBenchmarksMetricsMap, BenchmarkMetricsAggregate, AllBenchmarkMetricStatsMap, StatsNode, BenchmarkMetricStatsMap, StatsNodeGroup, MetricsStatsMap } from "@best/types"; import { quantile, mean, median, variance, medianAbsoluteDeviation, compare as compareSamples } from './stats'; function computeSampleStats(arr: number[], samplesQuantileThreshold: number): BenchmarkStats { @@ -52,9 +52,12 @@ function collectResults(resultNode: BenchmarkResultNode, collector: AllBenchmark function createStatsStructure(node: BenchmarkResultNode, collector: AllBenchmarkMetricStatsMap): StatsNode { if (node.type === "benchmark") { const { name, type } = node; - const stats = collector[name]; - const metrics = Object.keys(stats).reduce((metricReducer: any, metric: string) => { - metricReducer[metric as BenchmarkMetricNames] = { stats: stats[metric as BenchmarkMetricNames] }; + const metricStats = collector[name]; + const metrics = Object.keys(metricStats).reduce((metricReducer: MetricsStatsMap, metric: string) => { + const stats = metricStats[metric as BenchmarkMetricNames]; + if (stats) { + metricReducer[metric as BenchmarkMetricNames] = { stats }; + } return metricReducer; }, {}); return { type, name, metrics }; diff --git a/packages/@best/cli/src/cli/index.ts b/packages/@best/cli/src/cli/index.ts index e81dac39..6dbfa191 100644 --- a/packages/@best/cli/src/cli/index.ts +++ b/packages/@best/cli/src/cli/index.ts @@ -79,7 +79,7 @@ export async function runCLI(argsCLI: CliConfig, projects: string[]) { return process.exit(0); } - const output = new Output(globalConfig, outputStream); + const output = new Output({}, outputStream); if (argsCLI.compareStats) { results = await runCompare(globalConfig, configs, outputStream); if (results) { diff --git a/packages/@best/cli/src/cli/output.ts b/packages/@best/cli/src/cli/output.ts index 95bdfa15..2adfa0a2 100644 --- a/packages/@best/cli/src/cli/output.ts +++ b/packages/@best/cli/src/cli/output.ts @@ -1,21 +1,26 @@ import Table from 'cli-table'; import chalk from 'chalk'; import Histogram from './histogram'; -import { computeSampleStats } from '@best/analyzer'; + import { BenchmarkMetricNames, BenchmarkResultsSnapshot, - EnvironmentConfig, GlobalConfig, StatsNode, + EnvironmentConfig, StatsNode, StatsResults } from "@best/types"; +import { OutputStream } from '@best/console-stream'; + +interface OutputConfig { + outputHistograms?: boolean; +} /* * The Output module can write a report or a comparison to a given stream based on a configuration. */ export default class Output { - config: any; - stream: any; - constructor(config: GlobalConfig, stream: any) { + config: OutputConfig; + stream: OutputStream; + constructor(config: OutputConfig, stream: OutputStream) { this.config = config || {}; this.stream = stream; } @@ -26,14 +31,13 @@ export default class Output { report(results: BenchmarkResultsSnapshot[]) { results.forEach((result: BenchmarkResultsSnapshot) => { const { benchmarkInfo: { benchmarkName, benchmarkFolder }, stats } = result; - // Optionally calculate totals for each metric. - if (this.config.outputTotals) { - this.generateTotal(stats); - } + // Stats table. this.writeStats(benchmarkName, benchmarkFolder, stats!); + // OS & Browser. this.writeEnvironment(result.environment); + // Optional histogram for each line in the stats table. if (this.config.outputHistograms) { this.writeHistograms(stats!); @@ -41,37 +45,6 @@ export default class Output { }); } - /* - * Add a new entry under `stats.benchmarks`, containing totals across all of the other entries. - */ - generateTotal(stats: any) { - const total: any = {}; - const metricPattern = new RegExp(`^(.*)$`); // this.config.outputMetricPattern - - function add(node: any) { - const children = node.benchmarks; - if (children) { - children.forEach((child: any) => { add(child); }); - } else { - Object.keys(node).forEach((metric: any) => { - if (metricPattern.test(metric) && metric !== 'name') { - const samples = total[metric] = total[metric] || []; - node[metric].samples.forEach((v: any, i: any) => { - samples[i] = (samples[i] || 0) + v; - }); - } - }); - } - } - - add(stats); - Object.keys(total).forEach(metric => { - total[metric] = computeSampleStats(total[metric], this.config); - }); - total.name = 'total'; - stats.benchmarks.push(total); - } - /* * Write a table of statistics for a single benchmark file. */ @@ -96,7 +69,7 @@ export default class Output { * Write browser and CPU load information. */ writeEnvironment({ browser, container }: EnvironmentConfig) { - const cpuLoad = container.load.cpuLoad; //.cpu.cpuLoad; + const cpuLoad = container.load.cpuLoad; const loadColor = cpuLoad < 10 ? 'green' : cpuLoad < 50 ? 'yellow' : 'red'; this.stream.write(' '); @@ -151,11 +124,8 @@ export default class Output { // Root benchmark if (benchmarkNode.type === "benchmark") { Object.keys(benchmarkNode.metrics).forEach((metric: string) => { - // if (!metricPattern.test(metric)) { - // return; - // } - - const metricValues = benchmarkNode.metrics[metric as BenchmarkMetricNames].stats; + const metricsStats = benchmarkNode.metrics[metric as BenchmarkMetricNames]; + const metricValues = metricsStats && metricsStats.stats; if (metricValues && metricValues.sampleSize) { const { sampleSize, mean, median, variance, medianAbsoluteDeviation } = metricValues; table.push([ @@ -242,7 +212,7 @@ export default class Output { } } -function padding(n: any) { +function padding(n: number) { return n > 0 ? Array.apply(null, Array((n - 1) * 3)) .map(() => ' ') diff --git a/packages/@best/types/src/stats.ts b/packages/@best/types/src/stats.ts index 0043d958..1a2987f8 100644 --- a/packages/@best/types/src/stats.ts +++ b/packages/@best/types/src/stats.ts @@ -20,15 +20,19 @@ export interface BenchmarkStats { medianAbsoluteDeviation: number, } -export type BenchmarkMetricsAggregate = { [key in BenchmarkMetricNames]?: number[] } -export type BenchmarkMetricStatsMap = { [key in BenchmarkMetricNames]?: BenchmarkStats; } +export type BenchmarkMetricsAggregate = { + [key in BenchmarkMetricNames]?: number[] +} +export type BenchmarkMetricStatsMap = { + [key in BenchmarkMetricNames]?: BenchmarkStats; +} // This type will hold as keys all benchmark names, and then an array with all results export interface AllBenchmarksMetricsMap { [key: string]: BenchmarkMetricsAggregate } export interface AllBenchmarkMetricStatsMap { [key: string]: BenchmarkMetricStatsMap; } export type MetricsStatsMap = { - [key in BenchmarkMetricNames]: { + [key in BenchmarkMetricNames]?: { stats: BenchmarkStats } }