mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
148 lines
4.7 KiB
Dart
148 lines
4.7 KiB
Dart
// Copyright 2014 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import 'dart:convert' show json;
|
|
import 'dart:math' as math;
|
|
|
|
double _doNormal(
|
|
{required double mean, required double stddev, required double x}) {
|
|
return (1.0 / (stddev * math.sqrt(2.0 * math.pi))) *
|
|
math.pow(math.e, -0.5 * math.pow((x - mean) / stddev, 2.0));
|
|
}
|
|
|
|
double _doMean(List<double> values) =>
|
|
values.reduce((double x, double y) => x + y) / values.length;
|
|
|
|
double _doStddev(List<double> values, double mean) {
|
|
double stddev = 0.0;
|
|
for (final double value in values) {
|
|
stddev += (value - mean) * (value - mean);
|
|
}
|
|
return math.sqrt(stddev / values.length);
|
|
}
|
|
|
|
double _doIntegral({
|
|
required double Function(double) func,
|
|
required double start,
|
|
required double stop,
|
|
required double resolution,
|
|
}) {
|
|
double result = 0.0;
|
|
while (start < stop) {
|
|
final double value = func(start);
|
|
result += resolution * value;
|
|
start += resolution;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/// Probability is defined as the probability that the mean is within the
|
|
/// [margin] of the true value.
|
|
double _doProbability({required double mean, required double stddev, required double margin}) {
|
|
return _doIntegral(
|
|
func: (double x) => _doNormal(mean: mean, stddev: stddev, x: x),
|
|
start: (1.0 - margin) * mean,
|
|
stop: (1.0 + margin) * mean,
|
|
resolution: 0.001,
|
|
);
|
|
}
|
|
|
|
/// This class knows how to format benchmark results for machine and human
|
|
/// consumption.
|
|
///
|
|
|
|
/// Example:
|
|
///
|
|
/// BenchmarkResultPrinter printer = BenchmarkResultPrinter();
|
|
/// printer.add(
|
|
/// description: 'Average frame time',
|
|
/// value: averageFrameTime,
|
|
/// unit: 'ms',
|
|
/// name: 'average_frame_time',
|
|
/// );
|
|
/// printer.printToStdout();
|
|
///
|
|
class BenchmarkResultPrinter {
|
|
|
|
final List<_BenchmarkResult> _results = <_BenchmarkResult>[];
|
|
|
|
/// Adds a benchmark result to the list of results.
|
|
///
|
|
/// [description] is a human-readable description of the result. [value] is a
|
|
/// result value. [unit] is the unit of measurement, such as "ms", "km", "h".
|
|
/// [name] is a computer-readable name of the result used as a key in the JSON
|
|
/// serialization of the results.
|
|
void addResult({ required String description, required double value, required String unit, required String name }) {
|
|
_results.add(_BenchmarkResult(description, value, unit, name));
|
|
}
|
|
|
|
/// Adds a benchmark result to the list of results and a probability of that
|
|
/// result.
|
|
///
|
|
/// The probability is calculated as the probability that the mean is +- 5% of
|
|
/// the true value.
|
|
///
|
|
/// See also [addResult].
|
|
void addResultStatistics({
|
|
required String description,
|
|
required List<double> values,
|
|
required String unit,
|
|
required String name,
|
|
}) {
|
|
final double mean = _doMean(values);
|
|
final double stddev = _doStddev(values, mean);
|
|
const double margin = 0.05;
|
|
final double probability = _doProbability(mean: mean, stddev: stddev, margin: margin);
|
|
_results.add(_BenchmarkResult(description, mean, unit, name));
|
|
_results.add(_BenchmarkResult('$description - probability margin of error $margin', probability,
|
|
'percent', '${name}_probability_5pct'));
|
|
}
|
|
|
|
/// Prints the results added via [addResult] to standard output, once as JSON
|
|
/// for computer consumption and once formatted as plain text for humans.
|
|
void printToStdout() {
|
|
// IMPORTANT: keep these values in sync with dev/devicelab/bin/tasks/microbenchmarks.dart
|
|
const String jsonStart = '================ RESULTS ================';
|
|
const String jsonEnd = '================ FORMATTED ==============';
|
|
const String jsonPrefix = ':::JSON:::';
|
|
|
|
print(jsonStart);
|
|
print('$jsonPrefix ${_printJson()}');
|
|
print(jsonEnd);
|
|
print(_printPlainText());
|
|
}
|
|
|
|
String _printJson() {
|
|
final Map<String, double> results = <String, double>{};
|
|
for (final _BenchmarkResult result in _results) {
|
|
results[result.name] = result.value;
|
|
}
|
|
return json.encode(results);
|
|
}
|
|
|
|
String _printPlainText() {
|
|
final StringBuffer buf = StringBuffer();
|
|
for (final _BenchmarkResult result in _results) {
|
|
buf.writeln('${result.description}: ${result.value.toStringAsFixed(1)} ${result.unit}');
|
|
}
|
|
return buf.toString();
|
|
}
|
|
}
|
|
|
|
class _BenchmarkResult {
|
|
_BenchmarkResult(this.description, this.value, this.unit, this.name);
|
|
|
|
/// Human-readable description of the result, e.g. "Average frame time".
|
|
final String description;
|
|
|
|
/// Result value that in agreement with [unit].
|
|
final double value;
|
|
|
|
/// Unit of measurement that is in agreement with [value].
|
|
final String unit;
|
|
|
|
/// Computer-readable name of the result.
|
|
final String name;
|
|
}
|