performance tests should be able to measure runs/sec rather than time
[WebKit-https.git] / PerformanceTests / resources / runner.js
index e14f966..4087eef 100644 (file)
@@ -49,7 +49,7 @@ PerfTestRunner.loadFile = function (path) {
     return xhr.responseText;
 }
 
-PerfTestRunner.computeStatistics = function (times) {
+PerfTestRunner.computeStatistics = function (times, unit) {
     var data = times.slice();
 
     // Add values from the smallest to the largest to avoid the loss of significance
@@ -76,14 +76,14 @@ PerfTestRunner.computeStatistics = function (times) {
     }
     result.variance = squareSum / data.length;
     result.stdev = Math.sqrt(result.variance);
-    result.unit = "ms";
+    result.unit = unit || "ms";
 
     return result;
 }
 
 PerfTestRunner.logStatistics = function (times) {
     this.log("");
-    var statistics = this.computeStatistics(times);
+    var statistics = this.computeStatistics(times, this.unit);
     this.printStatistics(statistics);
 }
 
@@ -117,7 +117,7 @@ PerfTestRunner._runLoop = function () {
         this.gc();
         window.setTimeout(function () { PerfTestRunner._runner(); }, 0);
     } else {
-        this.logStatistics(this._times);
+        this.logStatistics(this._results);
         this._doneFunction();
         if (window.layoutTestController)
             layoutTestController.notifyDone();
@@ -140,13 +140,27 @@ PerfTestRunner._runner = function () {
     // Assume totalTime can never be zero when _runFunction returns a number.
     var time = totalTime ? totalTime : Date.now() - start;
 
+    this.ignoreWarmUpAndLog(time);
+    this._runLoop();
+}
+
+PerfTestRunner.ignoreWarmUpAndLog = function (result) {
     this._completedRuns++;
+
+    var labeledResult = result + " " + this.unit;
     if (this._completedRuns <= 0)
-        this.log("Ignoring warm-up run (" + time + ")");
+        this.log("Ignoring warm-up run (" + labeledResult + ")");
     else {
-        this._times.push(time);
-        this.log(time);
+        this._results.push(result);
+        this.log(labeledResult);
     }
+}
+
+PerfTestRunner.initAndStartLoop = function() {
+    this._completedRuns = -1;
+    this.customRunFunction = null;
+    this._results = [];
+    this.log("Running " + this._runCount + " times");
     this._runLoop();
 }
 
@@ -155,14 +169,49 @@ PerfTestRunner.run = function (runFunction, loopsPerRun, runCount, doneFunction)
     this._loopsPerRun = loopsPerRun || 10;
     this._runCount = runCount || 20;
     this._doneFunction = doneFunction || function () {};
-    this._completedRuns = -1;
-    this.customRunFunction = null;
-    this._times = [];
+    this.unit = 'ms';
+    this.initAndStartLoop();
+}
 
-    this.log("Running " + this._runCount + " times");
+PerfTestRunner.runPerSecond = function (test) {
+    this._doneFunction = function () { if (test.done) test.done(); };
+    this._runCount = test.runCount || 20;
+    this._callsPerIteration = 1;
+    this.unit = 'runs/s';
+
+    this._test = test;
+    this._runner = this._perSecondRunner;
+    this.initAndStartLoop();
+}
+
+PerfTestRunner._perSecondRunner = function () {
+    var timeToRun = this._test.timeToRun || 750;
+    var totalTime = 0;
+    var i = 0;
+    var callsPerIteration = this._callsPerIteration;
+
+    if (this._test.setup)
+        this._test.setup();
+
+    while (totalTime < timeToRun) {
+        totalTime += this._perSecondRunnerIterator(callsPerIteration);
+        i += callsPerIteration;
+        if (this._completedRuns <= 0 && totalTime < 100)
+            callsPerIteration = Math.max(10, 2 * callsPerIteration);
+    }
+    this._callsPerIteration = callsPerIteration;
+
+    this.ignoreWarmUpAndLog(i * 1000 / totalTime);
     this._runLoop();
 }
 
+PerfTestRunner._perSecondRunnerIterator = function (callsPerIteration) {
+    var startTime = Date.now();
+    for (var i = 0; i < callsPerIteration; i++)
+        this._test.run();
+    return Date.now() - startTime;
+}
+
 if (window.layoutTestController) {
     layoutTestController.waitUntilDone();
     layoutTestController.dumpAsText();