13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Simple framework for running the benchmark suites and 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// computing a score based on the timing measurements. 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A benchmark has a name (string) and a function that will be run to 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// do the performance measurement. The optional setup and tearDown 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// arguments are functions that will be invoked before and after 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// running the benchmark, but the running time of these functions will 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// not be accounted for in the benchmark score. 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction Benchmark(name, run, setup, tearDown) { 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.name = name; 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.run = run; 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.Setup = setup ? setup : function() { }; 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.TearDown = tearDown ? tearDown : function() { }; 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Benchmark results hold the benchmark and the measured time used to 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// run the benchmark. The benchmark score is computed later once a 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// full benchmark suite has run to completion. 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction BenchmarkResult(benchmark, time) { 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.benchmark = benchmark; 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.time = time; 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Automatically convert results to numbers. Used by the geometric 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// mean computation. 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockBenchmarkResult.prototype.valueOf = function() { 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return this.time; 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Suites of benchmarks consist of a name and the set of benchmarks in 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// addition to the reference timing that the final score will be based 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// on. This way, all scores are relative to a reference run and higher 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// scores implies better performance. 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction BenchmarkSuite(name, reference, benchmarks) { 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.name = name; 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.reference = reference; 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.benchmarks = benchmarks; 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BenchmarkSuite.suites.push(this); 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Keep track of all declared benchmark suites. 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockBenchmarkSuite.suites = []; 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Scores are not comparable across versions. Bump the version if 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// you're making changes that will affect that scores, e.g. if you add 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// a new benchmark or change an existing one. 813ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochBenchmarkSuite.version = '7'; 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// To make the benchmark results predictable, we replace Math.random 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with a 100% deterministic alternative. 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockMath.random = (function() { 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var seed = 49734321; 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return function() { 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Robert Jenkins' 32 bit integer hash function. 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block seed = ((seed + 0x7ed55d16) + (seed << 12)) & 0xffffffff; 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block seed = ((seed ^ 0xc761c23c) ^ (seed >>> 19)) & 0xffffffff; 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block seed = ((seed + 0x165667b1) + (seed << 5)) & 0xffffffff; 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block seed = ((seed + 0xd3a2646c) ^ (seed << 9)) & 0xffffffff; 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block seed = ((seed + 0xfd7046c5) + (seed << 3)) & 0xffffffff; 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block seed = ((seed ^ 0xb55a4f09) ^ (seed >>> 16)) & 0xffffffff; 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return (seed & 0xfffffff) / 0x10000000; 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }; 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block})(); 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Runs all registered benchmark suites and optionally yields between 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// each individual benchmark to avoid running for too long in the 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// context of browsers. Once done, the final score is reported to the 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// runner. 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockBenchmarkSuite.RunSuites = function(runner) { 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var continuation = null; 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var suites = BenchmarkSuite.suites; 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var length = suites.length; 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BenchmarkSuite.scores = []; 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var index = 0; 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block function RunStep() { 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (continuation || index < length) { 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (continuation) { 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block continuation = continuation(); 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var suite = suites[index++]; 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (runner.NotifyStart) runner.NotifyStart(suite.name); 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block continuation = suite.RunStep(runner); 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (continuation && typeof window != 'undefined' && window.setTimeout) { 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block window.setTimeout(RunStep, 25); 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (runner.NotifyScore) { 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var score = BenchmarkSuite.GeometricMean(BenchmarkSuite.scores); 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var formatted = BenchmarkSuite.FormatScore(100 * score); 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block runner.NotifyScore(formatted); 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RunStep(); 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Counts the total number of registered benchmarks. Useful for 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// showing progress as a percentage. 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockBenchmarkSuite.CountBenchmarks = function() { 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var result = 0; 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var suites = BenchmarkSuite.suites; 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (var i = 0; i < suites.length; i++) { 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result += suites[i].benchmarks.length; 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Computes the geometric mean of a set of numbers. 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockBenchmarkSuite.GeometricMean = function(numbers) { 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var log = 0; 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (var i = 0; i < numbers.length; i++) { 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block log += Math.log(numbers[i]); 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Math.pow(Math.E, log / numbers.length); 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Converts a score value to a string with at least three significant 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// digits. 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockBenchmarkSuite.FormatScore = function(value) { 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (value > 100) { 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return value.toFixed(0); 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return value.toPrecision(3); 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Notifies the runner that we're done running a single benchmark in 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the benchmark suite. This can be useful to report progress. 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockBenchmarkSuite.prototype.NotifyStep = function(result) { 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.results.push(result); 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (this.runner.NotifyStep) this.runner.NotifyStep(result.benchmark.name); 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Notifies the runner that we're done with running a suite and that 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// we have a result which can be reported to the user if needed. 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockBenchmarkSuite.prototype.NotifyResult = function() { 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var mean = BenchmarkSuite.GeometricMean(this.results); 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var score = this.reference / mean; 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BenchmarkSuite.scores.push(score); 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (this.runner.NotifyResult) { 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var formatted = BenchmarkSuite.FormatScore(100 * score); 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.runner.NotifyResult(this.name, formatted); 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Notifies the runner that running a benchmark resulted in an error. 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockBenchmarkSuite.prototype.NotifyError = function(error) { 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (this.runner.NotifyError) { 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.runner.NotifyError(this.name, error); 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (this.runner.NotifyStep) { 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.runner.NotifyStep(this.name); 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Runs a single benchmark for at least a second and computes the 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// average time it takes to run a single iteration. 2018defd9ff6930b4e24729971a61cf7469daf119beSteve BlockBenchmarkSuite.prototype.RunSingleBenchmark = function(benchmark, data) { 2028defd9ff6930b4e24729971a61cf7469daf119beSteve Block function Measure(data) { 2038defd9ff6930b4e24729971a61cf7469daf119beSteve Block var elapsed = 0; 2048defd9ff6930b4e24729971a61cf7469daf119beSteve Block var start = new Date(); 2058defd9ff6930b4e24729971a61cf7469daf119beSteve Block for (var n = 0; elapsed < 1000; n++) { 2068defd9ff6930b4e24729971a61cf7469daf119beSteve Block benchmark.run(); 2078defd9ff6930b4e24729971a61cf7469daf119beSteve Block elapsed = new Date() - start; 2088defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 2098defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (data != null) { 2108defd9ff6930b4e24729971a61cf7469daf119beSteve Block data.runs += n; 2118defd9ff6930b4e24729971a61cf7469daf119beSteve Block data.elapsed += elapsed; 2128defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 2138defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 2148defd9ff6930b4e24729971a61cf7469daf119beSteve Block 2158defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (data == null) { 2168defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Measure the benchmark once for warm up and throw the result 2178defd9ff6930b4e24729971a61cf7469daf119beSteve Block // away. Return a fresh data object. 2188defd9ff6930b4e24729971a61cf7469daf119beSteve Block Measure(null); 2198defd9ff6930b4e24729971a61cf7469daf119beSteve Block return { runs: 0, elapsed: 0 }; 2208defd9ff6930b4e24729971a61cf7469daf119beSteve Block } else { 2218defd9ff6930b4e24729971a61cf7469daf119beSteve Block Measure(data); 2228defd9ff6930b4e24729971a61cf7469daf119beSteve Block // If we've run too few iterations, we continue for another second. 2238defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (data.runs < 32) return data; 2248defd9ff6930b4e24729971a61cf7469daf119beSteve Block var usec = (data.elapsed * 1000) / data.runs; 2258defd9ff6930b4e24729971a61cf7469daf119beSteve Block this.NotifyStep(new BenchmarkResult(benchmark, usec)); 2268defd9ff6930b4e24729971a61cf7469daf119beSteve Block return null; 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This function starts running a suite, but stops between each 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// individual benchmark in the suite and returns a continuation 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// function which can be invoked to run the next benchmark. Once the 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// last benchmark has been executed, null is returned. 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockBenchmarkSuite.prototype.RunStep = function(runner) { 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.results = []; 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.runner = runner; 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var length = this.benchmarks.length; 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var index = 0; 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var suite = this; 2418defd9ff6930b4e24729971a61cf7469daf119beSteve Block var data; 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Run the setup, the actual benchmark, and the tear down in three 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // separate steps to allow the framework to yield between any of the 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // steps. 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block function RunNextSetup() { 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (index < length) { 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block try { 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block suite.benchmarks[index].Setup(); 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } catch (e) { 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block suite.NotifyError(e); 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return null; 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return RunNextBenchmark; 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block suite.NotifyResult(); 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return null; 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block function RunNextBenchmark() { 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block try { 2638defd9ff6930b4e24729971a61cf7469daf119beSteve Block data = suite.RunSingleBenchmark(suite.benchmarks[index], data); 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } catch (e) { 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block suite.NotifyError(e); 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return null; 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2688defd9ff6930b4e24729971a61cf7469daf119beSteve Block // If data is null, we're done with this benchmark. 2698defd9ff6930b4e24729971a61cf7469daf119beSteve Block return (data == null) ? RunNextTearDown : RunNextBenchmark(); 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block function RunNextTearDown() { 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block try { 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block suite.benchmarks[index++].TearDown(); 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } catch (e) { 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block suite.NotifyError(e); 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return null; 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return RunNextSetup; 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Start out running the setup. 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return RunNextSetup(); 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 285