mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 08:41:10 +00:00
d7057b2d8c
This CL is identical to 18555. The reason it will work now is the corresponding dartium change has been checked in. TBR-blois BUG= Review URL: https://codereview.chromium.org//12254046 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@18562 260f80e4-7a28-3924-810f-c04153c831b5
201 lines
5.8 KiB
Dart
201 lines
5.8 KiB
Dart
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
part of benchmark_lib;
|
|
|
|
/** Accessors for our Singleton variables. */
|
|
BenchmarkSuite get BENCHMARK_SUITE {
|
|
if (BenchmarkSuite._ONLY == null) {
|
|
BenchmarkSuite._ONLY = new BenchmarkSuite._internal();
|
|
}
|
|
return BenchmarkSuite._ONLY;
|
|
}
|
|
|
|
BenchmarkView get BENCHMARK_VIEW {
|
|
if (BenchmarkView._ONLY == null) {
|
|
BenchmarkView._ONLY = new BenchmarkView._internal();
|
|
}
|
|
return BenchmarkView._ONLY;
|
|
}
|
|
|
|
/** The superclass from which all benchmarks inherit from. */
|
|
class BenchmarkBase {
|
|
/** Benchmark name. */
|
|
final String name;
|
|
|
|
const BenchmarkBase(String name) : this.name = name;
|
|
|
|
/**
|
|
* The benchmark code.
|
|
* This function is not used, if both [warmup] and [exercise] are overwritten.
|
|
*/
|
|
void run() { }
|
|
|
|
/** Runs a short version of the benchmark. By default invokes [run] once. */
|
|
void warmup() {
|
|
run();
|
|
}
|
|
|
|
/** Exercices the benchmark. By default invokes [run] 10 times. */
|
|
void exercise() {
|
|
for (int i = 0; i < 10; i++) {
|
|
run();
|
|
}
|
|
}
|
|
|
|
/** Not measured setup code executed prior to the benchmark runs. */
|
|
void setup() { }
|
|
|
|
/** Not measures teardown code executed after the benchark runs. */
|
|
void teardown() { }
|
|
|
|
/**
|
|
* Measures the score for this benchmark by executing it repeately until
|
|
* time minimum has been reached.
|
|
*/
|
|
static double measureFor(Function f, int timeMinimum) {
|
|
int time = 0;
|
|
int iter = 0;
|
|
Stopwatch watch = new Stopwatch();
|
|
watch.start();
|
|
int elapsed = 0;
|
|
while (elapsed < timeMinimum || iter < 32) {
|
|
f();
|
|
elapsed = watch.elapsedMilliseconds;
|
|
iter++;
|
|
}
|
|
return (1000.0 * iter) / elapsed;
|
|
}
|
|
|
|
/**
|
|
* Measures the score for the benchmark and returns it.
|
|
* We measure iterations / sec (so bigger = better!).
|
|
*/
|
|
double measure() {
|
|
setup();
|
|
// Warmup for at least 1000ms. Discard result.
|
|
measureFor(() { this.warmup(); }, 1000);
|
|
// Run the benchmark for at least 1000ms.
|
|
double result = measureFor(() { this.exercise(); }, 1000);
|
|
teardown();
|
|
return result;
|
|
}
|
|
|
|
void report() {
|
|
num score = measure();
|
|
Map<String, int> normalizingDict = {'Smoketest': 100};
|
|
score = score / normalizingDict[name];
|
|
BENCHMARK_SUITE.updateIndividualScore(name, score);
|
|
}
|
|
}
|
|
|
|
/** The controller class that runs all of the benchmarks. */
|
|
class BenchmarkSuite {
|
|
/** The set of benchmarks that have yet to run. */
|
|
List<Function> benchmarks;
|
|
|
|
/**
|
|
* The set of scores from the benchmarks that have already run. (Used for
|
|
* calculating the Geometric mean).
|
|
*/
|
|
List<num> scores;
|
|
|
|
/** The total number of benchmarks we will be running. */
|
|
int totalBenchmarks;
|
|
|
|
/** Singleton pattern: There's only one BenchmarkSuite. */
|
|
static BenchmarkSuite _ONLY = null;
|
|
|
|
BenchmarkSuite._internal() {
|
|
scores = [];
|
|
benchmarks = [() => Smoketest.main()];
|
|
totalBenchmarks = benchmarks.length;
|
|
}
|
|
|
|
/** Run all of the benchmarks that we have in our benchmarks list. */
|
|
runBenchmarks() {
|
|
runBenchmarksHelper(benchmarks);
|
|
}
|
|
|
|
/**
|
|
* Run the remaining benchmarks in our list. We chain the calls providing
|
|
* little breaks for the main page to gain control, so we don't force the
|
|
* entire page to hang the whole time.
|
|
*/
|
|
runBenchmarksHelper(List<Function> remainingBenchmarks) {
|
|
// Remove the last benchmark, and run it.
|
|
var benchmark = remainingBenchmarks.removeLast();
|
|
benchmark();
|
|
if (remainingBenchmarks.length > 0) {
|
|
/* Provide small breaks between each benchmark, so that the browser
|
|
doesn't get unhappy about long running scripts, and so the user
|
|
can regain control of the UI to kill the page as needed. */
|
|
new Timer(const Duration(milliseconds: 25),
|
|
() => runBenchmarksHelper(remainingBenchmarks));
|
|
} else if (remainingBenchmarks.length == 0) {
|
|
// We've run all of the benchmarks. Update the page with the score.
|
|
BENCHMARK_VIEW.setScore(geometricMean(scores));
|
|
}
|
|
}
|
|
|
|
/** Store the results of a single benchmark run. */
|
|
updateIndividualScore(String name, num score) {
|
|
scores.add(score);
|
|
BENCHMARK_VIEW.incrementProgress(name, score, totalBenchmarks);
|
|
}
|
|
|
|
/** Computes the geometric mean of a set of numbers. */
|
|
geometricMean(numbers) {
|
|
num log = 0;
|
|
for (num n in numbers) {
|
|
log += Math.log(n);
|
|
}
|
|
return Math.pow(Math.E, log / numbers.length);
|
|
}
|
|
}
|
|
|
|
/** Controls how results are displayed to the user, by updating the HTML. */
|
|
class BenchmarkView {
|
|
|
|
/** The number of benchmarks that have finished executing. */
|
|
int numCompleted = 0;
|
|
|
|
/** Singleton pattern: There's only one BenchmarkSuite. */
|
|
static BenchmarkView _ONLY = null;
|
|
|
|
BenchmarkView._internal();
|
|
|
|
/** Update the page HTML to show the calculated score. */
|
|
setScore(num score) {
|
|
String newScore = formatScore(score * 100.0);
|
|
Element body = document.queryAll("body")[0];
|
|
body.nodes.add(
|
|
new Element.html("<p id='testResultScore'>Score: $newScore</p>"));
|
|
}
|
|
|
|
/**
|
|
* Update the page HTML to show how much progress we've made through the
|
|
* benchmarks.
|
|
*/
|
|
incrementProgress(String name, num score, num totalBenchmarks) {
|
|
String newScore = formatScore(score * 100.0);
|
|
numCompleted++;
|
|
// Slightly incorrect (truncating) percentage, but this is just to show
|
|
// the user we're making progress.
|
|
num percentage = 100 * numCompleted ~/ totalBenchmarks;
|
|
}
|
|
|
|
/**
|
|
* Rounds the score to have at least three significant digits (hopefully)
|
|
* helping readability of the scores.
|
|
*/
|
|
String formatScore(num value) {
|
|
if (value > 100) {
|
|
return value.toStringAsFixed(0);
|
|
} else {
|
|
return value.toStringAsFixed(2);
|
|
}
|
|
}
|
|
}
|