1 // There are tests for computeStatistics() located in LayoutTests/fast/harness/perftests
3 var PerfTestRunner = {};
5 // To make the benchmark results predictable, we replace Math.random with a
6 // 100% deterministic alternative.
7 PerfTestRunner.randomSeed = PerfTestRunner.initialRandomSeed = 49734321;
9 PerfTestRunner.resetRandomSeed = function() {
10 PerfTestRunner.randomSeed = PerfTestRunner.initialRandomSeed
13 PerfTestRunner.random = Math.random = function() {
14 // Robert Jenkins' 32 bit integer hash function.
15 var randomSeed = PerfTestRunner.randomSeed;
16 randomSeed = ((randomSeed + 0x7ed55d16) + (randomSeed << 12)) & 0xffffffff;
17 randomSeed = ((randomSeed ^ 0xc761c23c) ^ (randomSeed >>> 19)) & 0xffffffff;
18 randomSeed = ((randomSeed + 0x165667b1) + (randomSeed << 5)) & 0xffffffff;
19 randomSeed = ((randomSeed + 0xd3a2646c) ^ (randomSeed << 9)) & 0xffffffff;
20 randomSeed = ((randomSeed + 0xfd7046c5) + (randomSeed << 3)) & 0xffffffff;
21 randomSeed = ((randomSeed ^ 0xb55a4f09) ^ (randomSeed >>> 16)) & 0xffffffff;
22 PerfTestRunner.randomSeed = randomSeed;
23 return (randomSeed & 0xfffffff) / 0x10000000;
26 PerfTestRunner.log = function (text) {
28 this._logLines.push(text);
31 if (!document.getElementById("log")) {
32 var pre = document.createElement('pre');
34 document.body.appendChild(pre);
36 document.getElementById("log").innerHTML += text + "\n";
37 window.scrollTo(0, document.body.height);
40 PerfTestRunner.info = function (text) {
41 this.log("Info: " + text);
44 PerfTestRunner.logInfo = function (text) {
45 if (!window.layoutTestController)
49 PerfTestRunner.loadFile = function (path) {
50 var xhr = new XMLHttpRequest();
51 xhr.open("GET", path, false);
53 return xhr.responseText;
56 PerfTestRunner.computeStatistics = function (times, unit) {
57 var data = times.slice();
59 // Add values from the smallest to the largest to avoid the loss of significance
60 data.sort(function(a,b){return a-b;});
62 var middle = Math.floor(data.length / 2);
65 max: data[data.length - 1],
66 median: data.length % 2 ? data[middle] : (data[middle - 1] + data[middle]) / 2,
69 // Compute the mean and variance using a numerically stable algorithm.
71 result.mean = data[0];
73 for (var i = 1; i < data.length; ++i) {
75 var delta = x - result.mean;
77 result.mean += delta / sweep;
79 squareSum += delta * delta * (i / sweep);
81 result.variance = squareSum / data.length;
82 result.stdev = Math.sqrt(result.variance);
83 result.unit = unit || "ms";
88 PerfTestRunner.logStatistics = function (times) {
90 var statistics = this.computeStatistics(times, this.unit);
91 this.printStatistics(statistics);
94 PerfTestRunner.printStatistics = function (statistics) {
96 this.log("avg " + statistics.mean + " " + statistics.unit);
97 this.log("median " + statistics.median + " " + statistics.unit);
98 this.log("stdev " + statistics.stdev + " " + statistics.unit);
99 this.log("min " + statistics.min + " " + statistics.unit);
100 this.log("max " + statistics.max + " " + statistics.unit);
103 PerfTestRunner.gc = function () {
104 if (window.GCController)
105 window.GCController.collect();
110 var temp = {i: "ab" + i + (i / 100000)};
114 for (var i = 0; i < 1000; i++)
119 PerfTestRunner._runLoop = function () {
120 if (this._completedRuns < this._runCount) {
122 window.setTimeout(function () { PerfTestRunner._runner(); }, 0);
124 if (this._description)
125 this.log("Description: " + this._description);
126 this.logStatistics(this._results);
127 if (this._logLines) {
128 var logLines = this._logLines;
129 this._logLines = null;
131 logLines.forEach(function(text) { self.log(text); });
133 this._doneFunction();
134 if (window.layoutTestController)
135 layoutTestController.notifyDone();
139 PerfTestRunner._runner = function () {
140 var start = Date.now();
143 for (var i = 0; i < this._loopsPerRun; ++i) {
144 var returnValue = this._runFunction.call(window);
145 if (returnValue - 0 === returnValue) {
146 if (returnValue <= 0)
147 this.log("runFunction returned a non-positive value: " + returnValue);
148 totalTime += returnValue;
152 // Assume totalTime can never be zero when _runFunction returns a number.
153 var time = totalTime ? totalTime : Date.now() - start;
155 this.ignoreWarmUpAndLog(time);
159 PerfTestRunner.ignoreWarmUpAndLog = function (result) {
160 this._completedRuns++;
162 var labeledResult = result + " " + this.unit;
163 if (this._completedRuns <= 0)
164 this.log("Ignoring warm-up run (" + labeledResult + ")");
166 this._results.push(result);
167 this.log(labeledResult);
171 PerfTestRunner.initAndStartLoop = function() {
172 this._completedRuns = -1;
173 this.customRunFunction = null;
175 this._logLines = window.layoutTestController ? [] : null;
176 this.log("Running " + this._runCount + " times");
180 PerfTestRunner.run = function (runFunction, loopsPerRun, runCount, doneFunction, description) {
181 this._runFunction = runFunction;
182 this._loopsPerRun = loopsPerRun || 10;
183 this._runCount = runCount || 20;
184 this._doneFunction = doneFunction || function () {};
185 this._description = description || "";
187 this.initAndStartLoop();
190 PerfTestRunner.runPerSecond = function (test) {
191 this._doneFunction = function () { if (test.done) test.done(); };
192 this._description = test.description || "";
193 this._runCount = test.runCount || 20;
194 this._callsPerIteration = 1;
195 this.unit = 'runs/s';
198 this._runner = this._perSecondRunner;
199 this.initAndStartLoop();
202 PerfTestRunner._perSecondRunner = function () {
203 var timeToRun = this._test.timeToRun || 750;
206 var callsPerIteration = this._callsPerIteration;
208 if (this._test.setup)
211 while (totalTime < timeToRun) {
212 totalTime += this._perSecondRunnerIterator(callsPerIteration);
213 i += callsPerIteration;
214 if (this._completedRuns < 0 && totalTime < 100)
215 callsPerIteration = Math.max(10, 2 * callsPerIteration);
217 this._callsPerIteration = callsPerIteration;
219 this.ignoreWarmUpAndLog(i * 1000 / totalTime);
223 PerfTestRunner._perSecondRunnerIterator = function (callsPerIteration) {
224 var startTime = Date.now();
225 for (var i = 0; i < callsPerIteration; i++)
227 return Date.now() - startTime;
230 if (window.layoutTestController) {
231 layoutTestController.waitUntilDone();
232 layoutTestController.dumpAsText();