Make DoYouEvenBench runnable by run-perf-tests
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 15 Jan 2014 08:01:52 +0000 (08:01 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 15 Jan 2014 08:01:52 +0000 (08:01 +0000)
https://bugs.webkit.org/show_bug.cgi?id=127030

Reviewed by Andreas Kling.

PerformanceTests:

Added Full.html that runs 5 iterations of DoYouEvenBench. This is the canonical DoYouEvenBench,
which is also runnable by run-perf-tests.

* DoYouEvenBench/Full.html: Added.

* DoYouEvenBench/benchmark.html:
(startTest): Updated the code to account for the fact old measuredValues is pushed down to tests
property and we now have total property so that we don't have to manually compute the total.

* DoYouEvenBench/resources/benchmark-report.js: Added. When we're inside a DRT/WTR, use
PerfTestRunner to output that can be parsed by run-perf-tests. Do the same when the query part
or the fragment part of the current URL is "webkit" for debugging purposes.

* DoYouEvenBench/resources/benchmark-runner.js:
(BenchmarkRunner):
(BenchmarkRunner.prototype._appendFrame): Position the frame at (0, 0) inside DRT and WTR since
we have exactly 800px by 600px inside those two test runners. Also always insert the iframe as
the first child of body to avoid inserting it after the pre inserted by the test runner.
(BenchmarkRunner.prototype.step): Initializes _measuredValues.
(BenchmarkRunner.prototype.runAllSteps): Merged callNextStep in benchmark.html.
(BenchmarkRunner.prototype.runMultipleIterations): Added.
(BenchmarkRunner.prototype._runTestAndRecordResults): Compute the grand total among suites.
Also push down the sync and async time into tests property for consistency.
(BenchmarkRunner.prototype._finalize):

* Dromaeo/resources/dromaeorunner.js:
(DRT.testObject): Renamed dromaeoIterationCount to customIterationCount as this option is also
used by DoYouEvenBench.

* resources/runner.js: Ditto.
(.finish): Spit out the aggregator name.

Tools:

Ignore console messages spit out by DoYouEvenBench and support aggregator names such as
":Total" to appear at the end of a test name. We don't do anything with it for now.

* Scripts/webkitpy/performance_tests/perftest.py:
(PerfTest._metrics_regex): Handle aggregator names such as ":Total". We'll pass it down
to the JSON in a follow up patch for the perf dashboard.
(PerfTest._lines_to_ignore_in_parser_result): Added lines to ignore for DoYouEvenBench.

LayoutTests:

Use customIterationCount as it has been renamed from dromaeoIterationCount.

* fast/harness/perftests/runs-per-second-iterations.html:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@162058 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/harness/perftests/runs-per-second-iterations.html
PerformanceTests/ChangeLog
PerformanceTests/DoYouEvenBench/Full.html [new file with mode: 0644]
PerformanceTests/DoYouEvenBench/benchmark.html
PerformanceTests/DoYouEvenBench/resources/benchmark-report.js [new file with mode: 0644]
PerformanceTests/DoYouEvenBench/resources/benchmark-runner.js
PerformanceTests/Dromaeo/resources/dromaeorunner.js
PerformanceTests/resources/runner.js
Tools/ChangeLog
Tools/Scripts/webkitpy/performance_tests/perftest.py

index 4e876f2..9901ab3 100644 (file)
@@ -1,3 +1,14 @@
+2014-01-14  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Make DoYouEvenBench runnable by run-perf-tests
+        https://bugs.webkit.org/show_bug.cgi?id=127030
+
+        Reviewed by Andreas Kling.
+
+        Use customIterationCount as it has been renamed from dromaeoIterationCount.
+
+        * fast/harness/perftests/runs-per-second-iterations.html:
+
 2014-01-14  Dirk Schulze  <krit@webkit.org>
 
         Remove unnecessary WebkitCSSSVGDocumentValue
index 730f734..4278f02 100644 (file)
@@ -33,7 +33,7 @@ PerfTestRunner.measureRunsPerSecond({
             callsInIterations[i] = 0;
         callsInIterations[i]++;
     },
-    dromaeoIterationCount: 1,
+    customIterationCount: 1,
     done: function () {
         debug("Returning times: [" + originalTimesInIterations.join(", ") + "]");
         shouldEvaluateTo("callsInIterations[0]", 1);
index 222114a..214fa96 100644 (file)
@@ -1,3 +1,42 @@
+2014-01-14  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Make DoYouEvenBench runnable by run-perf-tests
+        https://bugs.webkit.org/show_bug.cgi?id=127030
+
+        Reviewed by Andreas Kling.
+
+        Added Full.html that runs 5 iterations of DoYouEvenBench. This is the canonical DoYouEvenBench,
+        which is also runnable by run-perf-tests.
+
+        * DoYouEvenBench/Full.html: Added.
+
+        * DoYouEvenBench/benchmark.html:
+        (startTest): Updated the code to account for the fact old measuredValues is pushed down to tests
+        property and we now have total property so that we don't have to manually compute the total.
+
+        * DoYouEvenBench/resources/benchmark-report.js: Added. When we're inside a DRT/WTR, use
+        PerfTestRunner to output that can be parsed by run-perf-tests. Do the same when the query part
+        or the fragment part of the current URL is "webkit" for debugging purposes.
+
+        * DoYouEvenBench/resources/benchmark-runner.js:
+        (BenchmarkRunner):
+        (BenchmarkRunner.prototype._appendFrame): Position the frame at (0, 0) inside DRT and WTR since
+        we have exactly 800px by 600px inside those two test runners. Also always insert the iframe as
+        the first child of body to avoid inserting it after the pre inserted by the test runner.
+        (BenchmarkRunner.prototype.step): Initializes _measuredValues.
+        (BenchmarkRunner.prototype.runAllSteps): Merged callNextStep in benchmark.html.
+        (BenchmarkRunner.prototype.runMultipleIterations): Added.
+        (BenchmarkRunner.prototype._runTestAndRecordResults): Compute the grand total among suites.
+        Also push down the sync and async time into tests property for consistency.
+        (BenchmarkRunner.prototype._finalize):
+
+        * Dromaeo/resources/dromaeorunner.js:
+        (DRT.testObject): Renamed dromaeoIterationCount to customIterationCount as this option is also
+        used by DoYouEvenBench.
+
+        * resources/runner.js: Ditto.
+        (.finish): Spit out the aggregator name.
+
 2014-01-07  Ryosuke Niwa  <rniwa@webkit.org>
 
         DoYouEvenBench: Turn BenchmarkRunner into a real class
diff --git a/PerformanceTests/DoYouEvenBench/Full.html b/PerformanceTests/DoYouEvenBench/Full.html
new file mode 100644 (file)
index 0000000..f659ead
--- /dev/null
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>DoYouEvenBench</title>
+<script>
+
+(function () {
+    var values = [];
+    var pre = null;
+    var iterationNumber = 0;
+    window.benchmarkClient = {
+        didRunSuites: function (measuredValues) {
+            if (!pre) {
+                pre = document.createElement('pre');
+                pre.style.paddingTop = '600px';
+                document.body.appendChild(pre);
+            }
+            values.push(measuredValues.total);
+            iterationNumber++;
+            pre.appendChild(document.createTextNode('Iteration ' + iterationNumber + ': ' + measuredValues.total + 'ms\n'));
+        },
+        didFinishLastIteration: function () {
+            var sum = 0;
+            for (var i = 0; i < values.length; i++)
+                sum += values[i];
+            pre.appendChild(document.createTextNode('Average: ' + (sum / iterationNumber)  + 'ms\n'));
+            pre.style.paddingTop = 0;
+        }
+    }
+})();
+
+function startTest() {
+    var iterationCount = 5;
+    var runner = new BenchmarkRunner(Suites, benchmarkClient);
+    runner.runMultipleIterations(iterationCount);
+}
+
+</script>
+<script src="resources/benchmark-runner.js"></script>
+<script src="resources/benchmark-report.js"></script>
+<script src="resources/tests.js"></script>
+</head>
+<body onload="startTest()">
+</body>
+</html>
index 2a0b769..97fd90b 100644 (file)
@@ -84,20 +84,18 @@ function startTest() {
         },
         didRunSuites: function (measuredValues) {
             var results = '';
-            var total = 0; // FIXME: Compute the total properly.
-            for (var suiteName in measuredValues) {
-                var suiteResults = measuredValues[suiteName];
+            for (var suiteName in measuredValues.tests) {
+                var suiteResults = measuredValues.tests[suiteName];
                 for (var testName in suiteResults.tests) {
                     var testResults = suiteResults.tests[testName];
-                    for (var subtestName in testResults) {
+                    for (var subtestName in testResults.tests) {
                         results += suiteName + ' : ' + testName + ' : ' + subtestName
-                            + ': ' + testResults[subtestName] + ' ms\n';
+                            + ': ' + testResults.tests[subtestName] + ' ms\n';
                     }
                 }
                 results += suiteName + ' : ' + suiteResults.total + ' ms\n';
-                total += suiteResults.total;
             }
-            results += 'Total : ' + total + ' ms\n';
+            results += 'Total : ' + measuredValues.total + ' ms\n';
 
             if (!results)
                 return;
@@ -109,18 +107,11 @@ function startTest() {
     });
 
     var currentState = null;
-    function callNextStep(state) {
-        runner.step(state).then(function (newState) {
-            currentState = newState;
-            if (newState)
-                callNextStep(newState);
-        });
-    }
 
     // Don't call step while step is already executing.
     document.body.appendChild(createUIForSuites(Suites,
         function () { runner.step(currentState).then(function (state) { currentState = state; }); },
-        function () { callNextStep(currentState); }));
+        function () { runner.runAllSteps(currentState); currentState = null; }));
 }
 
 window.addEventListener('load', startTest);
diff --git a/PerformanceTests/DoYouEvenBench/resources/benchmark-report.js b/PerformanceTests/DoYouEvenBench/resources/benchmark-report.js
new file mode 100644 (file)
index 0000000..0ea96c1
--- /dev/null
@@ -0,0 +1,73 @@
+// This file can be customized to report results as needed.
+
+(function () {
+    if (!window.testRunner && location.search != '?webkit' && location.hash != '#webkit')
+        return;
+
+    if (window.testRunner)
+        testRunner.waitUntilDone();
+
+    var scriptElement = document.createElement('script');
+    scriptElement.src = '../resources/runner.js';
+    document.head.appendChild(scriptElement);
+
+    var styleElement = document.createElement('style');
+    styleElement.textContent = 'pre { padding-top: 600px; }';
+    document.head.appendChild(styleElement);
+
+    var createTest;
+    var valuesByIteration = new Array;
+
+    window.benchmarkClient = {
+        willStartFirstIteration: function (iterationCount) {
+            createTest = function (name, aggregator, isLastTest) {
+                return {
+                    customIterationCount: iterationCount,
+                    doNotIgnoreInitialRun: true,
+                    doNotMeasureMemoryUsage: true,
+                    continueTesting: !isLastTest,
+                    unit: 'ms',
+                    name: name,
+                    aggregator: aggregator};
+            }
+            PerfTestRunner.prepareToMeasureValuesAsync(createTest(null, 'Total'));
+        },
+        didRunSuites: function (measuredValues) {
+            PerfTestRunner.measureValueAsync(measuredValues.total);
+            valuesByIteration.push(measuredValues.tests);
+        },
+        didFinishLastIteration: function () {
+            document.head.removeChild(document.querySelector('style'));
+
+            var measuredValuesByFullName = {};
+            function addToMeasuredValue(value, fullName, aggregator) {
+                var values = measuredValuesByFullName[fullName] || new Array;
+                measuredValuesByFullName[fullName] = values;
+                values.push(value);
+                values.aggregator = aggregator;
+            }
+
+            valuesByIteration.forEach(function (measuredValues) {
+                for (var suiteName in measuredValues) {
+                    var suite = measuredValues[suiteName];
+                    for (var testName in suite.tests) {
+                        var test = suite.tests[testName];
+                        for (var subtestName in test.tests)
+                            addToMeasuredValue(test.tests[subtestName], suiteName + '/' + testName + '/' + subtestName);
+                        addToMeasuredValue(test.total, suiteName + '/' + testName, 'Total');
+                    }
+                    addToMeasuredValue(suite.total, suiteName, 'Total');
+                }
+            });
+
+            var fullNames = new Array;
+            for (var fullName in measuredValuesByFullName)
+                fullNames.push(fullName);
+
+            for (var i = 0; i < fullNames.length; i++) {
+                var values = measuredValuesByFullName[fullNames[i]];
+                PerfTestRunner.reportValues(createTest(fullNames[i], values.aggregator, i + 1 == fullNames.length), values);
+            }
+        }
+    };
+})();
index 582c9af..c596abf 100644 (file)
@@ -40,7 +40,6 @@ function BenchmarkTestStep(testName, testFunction) {
 function BenchmarkRunner(suites, client) {
     this._suites = suites;
     this._prepareReturnValue = null;
-    this._measuredValues = {};
     this._client = client;
 }
 
@@ -69,8 +68,21 @@ BenchmarkRunner.prototype._removeFrame = function () {
 BenchmarkRunner.prototype._appendFrame = function (src) {
     var frame = document.createElement('iframe');
     frame.style.width = '800px';
-    frame.style.height = '600px'
-    document.body.appendChild(frame);
+    frame.style.height = '600px';
+    frame.style.border = '0px none';
+    frame.style.position = 'absolute';
+
+    var marginTop = document.body.style.marginTop;
+    var marginBottom = document.body.style.marginBottom;
+    if (window.innerWidth > 800 + marginTop && window.innerHeight > 600 + marginBottom) {
+        frame.style.left = marginTop + 'px';
+        frame.style.top = marginBottom + 'px';
+    } else {
+        frame.style.left = '0px';
+        frame.style.top = '0px';
+    }
+
+    document.body.insertBefore(frame, document.body.firstChild);
     this._frame = frame;
     return frame;
 }
@@ -162,8 +174,10 @@ BenchmarkState.prototype.prepareCurrentSuite = function (runner, frame) {
 }
 
 BenchmarkRunner.prototype.step = function (state) {
-    if (!state)
+    if (!state) {
         state = new BenchmarkState(this._suites);
+        this._measuredValues = {tests: {}, total: 0};
+    }
 
     var suite = state.currentSuite();
     if (!suite) {
@@ -185,6 +199,32 @@ BenchmarkRunner.prototype.step = function (state) {
     return this._runTestAndRecordResults(state);
 }
 
+BenchmarkRunner.prototype.runAllSteps = function (startingState) {
+    var nextCallee = this.runAllSteps.bind(this);
+    this.step(startingState).then(function (nextState) {
+        if (nextState)
+            nextCallee(nextState);
+    });
+}
+
+BenchmarkRunner.prototype.runMultipleIterations = function (iterationCount) {
+    var self = this;
+    var currentIteration = 0;
+
+    this._runNextIteration = function () {
+        currentIteration++;
+        if (currentIteration < iterationCount)
+            self.runAllSteps();
+        else if (this._client && this._client.didFinishLastIteration)
+            this._client.didFinishLastIteration();
+    }
+
+    if (this._client && this._client.willStartFirstIteration)
+        this._client.willStartFirstIteration(iterationCount);
+
+    self.runAllSteps();
+}
+
 BenchmarkRunner.prototype._runTestAndRecordResults = function (state) {
     var promise = new SimplePromise;
     var suite = state.currentSuite();
@@ -196,10 +236,12 @@ BenchmarkRunner.prototype._runTestAndRecordResults = function (state) {
     var self = this;
     setTimeout(function () {
         self._runTest(suite, test.run, self._prepareReturnValue, function (syncTime, asyncTime) {
-            var suiteResults = self._measuredValues[suite.name] || {tests:{}, total: 0};
-            self._measuredValues[suite.name] = suiteResults;
-            suiteResults.tests[test.name] = {'Sync': syncTime, 'Async': asyncTime};
-            suiteResults.total += syncTime + asyncTime;
+            var suiteResults = self._measuredValues.tests[suite.name] || {tests:{}, total: 0};
+            var total = syncTime + asyncTime;
+            self._measuredValues.tests[suite.name] = suiteResults;
+            suiteResults.tests[test.name] = {tests: {'Sync': syncTime, 'Async': asyncTime}, total: total};
+            suiteResults.total += total;
+            self._measuredValues.total += total;
 
             if (self._client && self._client.willRunTest)
                 self._client.didRunTest(suite, test);
@@ -219,6 +261,6 @@ BenchmarkRunner.prototype._finalize = function () {
     if (this._client && this._client.didRunSuites)
         this._client.didRunSuites(this._measuredValues);
 
-    // FIXME: This should be done when we start running tests.
-    this._measuredValues = {};
+    if (this._runNextIteration)
+        this._runNextIteration();
 }
index d74c3e9..1b05e8e 100644 (file)
@@ -32,7 +32,7 @@
          },
 
          testObject: function(name) {
-             return {dromaeoIterationCount: ITERATION_COUNT, doNotMeasureMemoryUsage: true, doNotIgnoreInitialRun: true, unit: 'runs/s',
+             return {customIterationCount: ITERATION_COUNT, doNotMeasureMemoryUsage: true, doNotIgnoreInitialRun: true, unit: 'runs/s',
                 name: name, continueTesting: !!name};
          },
 
index cf89331..ee1c630 100755 (executable)
@@ -153,7 +153,7 @@ if (window.testRunner) {
         currentTest = test;
         // FIXME: We should be using multiple instances of test runner on Dromaeo as well but it's too slow now.
         // FIXME: Don't hard code the number of in-process iterations to use inside a test runner.
-        iterationCount = test.dromaeoIterationCount || (window.testRunner ? 5 : 20);
+        iterationCount = test.customIterationCount || (window.testRunner ? 5 : 20);
         completedIterations = -1;
         results = [];
         jsHeapResults = [];
@@ -220,8 +220,9 @@ if (window.testRunner) {
             var prefix = currentTest.name || '';
             if (currentTest.description)
                 PerfTestRunner.log("Description: " + currentTest.description);
-            metric = {'fps': 'FrameRate', 'runs/s': 'Runs', 'ms': 'Time'}[PerfTestRunner.unit]
-            PerfTestRunner.logStatistics(results, PerfTestRunner.unit, prefix + ":" + metric);
+            metric = {'fps': 'FrameRate', 'runs/s': 'Runs', 'ms': 'Time'}[PerfTestRunner.unit];
+            var suffix = currentTest.aggregation ? ':' + currentTest.aggregation : '';
+            PerfTestRunner.logStatistics(results, PerfTestRunner.unit, prefix + ":" + metric + suffix);
             if (jsHeapResults.length) {
                 PerfTestRunner.logStatistics(jsHeapResults, "bytes", prefix + ":JSHeap");
                 PerfTestRunner.logStatistics(mallocHeapResults, "bytes", prefix + ":Malloc");
index 73df56b..0cf7928 100644 (file)
@@ -1,3 +1,18 @@
+2014-01-14  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Make DoYouEvenBench runnable by run-perf-tests
+        https://bugs.webkit.org/show_bug.cgi?id=127030
+
+        Reviewed by Andreas Kling.
+
+        Ignore console messages spit out by DoYouEvenBench and support aggregator names such as
+        ":Total" to appear at the end of a test name. We don't do anything with it for now.
+
+        * Scripts/webkitpy/performance_tests/perftest.py:
+        (PerfTest._metrics_regex): Handle aggregator names such as ":Total". We'll pass it down
+        to the JSON in a follow up patch for the perf dashboard.
+        (PerfTest._lines_to_ignore_in_parser_result): Added lines to ignore for DoYouEvenBench.
+
 2014-01-14  Carlos Garcia Campos  <cgarcia@igalia.com>
 
         [GTK] UI process crashes when the web process crashes while printing
index 4a9c763..b88aa55 100644 (file)
@@ -168,7 +168,7 @@ class PerfTest(object):
             (median, unit, stdev, unit, sorted_values[0], unit, sorted_values[-1], unit))
 
     _description_regex = re.compile(r'^Description: (?P<description>.*)$', re.IGNORECASE)
-    _metrics_regex = re.compile(r'^(?P<subtest>[A-Za-z0-9\(\[].+)?:(?P<metric>[A-Z][A-Za-z]+) -> \[(?P<values>(\d+(\.\d+)?)(, \d+(\.\d+)?)+)\] (?P<unit>[a-z/]+)?$')
+    _metrics_regex = re.compile(r'^(?P<subtest>[A-Za-z0-9\(\[].+)?:(?P<metric>[A-Z][A-Za-z]+)(:(?P<aggregator>[A-Z][A-Za-z]+))? -> \[(?P<values>(\d+(\.\d+)?)(, \d+(\.\d+)?)+)\] (?P<unit>[a-z/]+)?$')
 
     def _run_with_driver(self, driver, time_out_ms):
         output = self.run_single(driver, self.test_path(), time_out_ms)
@@ -246,6 +246,17 @@ class PerfTest(object):
         re.compile(re.escape("""Blocked access to external URL http://www.whatwg.org/specs/web-apps/current-work/""")),
         re.compile(r"CONSOLE MESSAGE: (line \d+: )?Blocked script execution in '[A-Za-z0-9\-\.:]+' because the document's frame is sandboxed and the 'allow-scripts' permission is not set."),
         re.compile(r"CONSOLE MESSAGE: (line \d+: )?Not allowed to load local resource"),
+        # DoYouEvenBench
+        re.compile(re.escape("CONSOLE MESSAGE: line 140: Miss the info bar? Run TodoMVC from a server to avoid a cross-origin error.")),
+        re.compile(re.escape("CONSOLE MESSAGE: line 315: TypeError: Attempted to assign to readonly property.")),
+        re.compile(re.escape("CONSOLE MESSAGE: line 339: DEBUG: -------------------------------")),
+        re.compile(re.escape("CONSOLE MESSAGE: line 339: DEBUG: Ember.VERSION : 1.0.0-rc.1")),
+        re.compile(re.escape("CONSOLE MESSAGE: line 339: DEBUG: Handlebars.VERSION : 1.0.0-rc.3")),
+        re.compile(re.escape("CONSOLE MESSAGE: line 339: DEBUG: jQuery.VERSION : 1.9.1")),
+        re.compile(re.escape("CONSOLE MESSAGE: line 339: DEPRECATION: Namespaces should not begin with lowercase")),
+        re.compile(re.escape("processAllNamespaces@ember.js:4359:36")),
+        re.compile(re.escape("CONSOLE MESSAGE: line 124: Booting in DEBUG mode")),
+        re.compile(re.escape("CONSOLE MESSAGE: line 125: You can configure event logging with DEBUG.events.logAll()/logNone()/logByName()/logByAction()")),
     ]
 
     def _filter_output(self, output):