Improve canvas perf test accuracy.
authorlevin@chromium.org <levin@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 25 May 2010 07:48:13 +0000 (07:48 +0000)
committerlevin@chromium.org <levin@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 25 May 2010 07:48:13 +0000 (07:48 +0000)
https://bugs.webkit.org/show_bug.cgi?id=39635

Reviewed by Maciej Stachowiak.

* demos/canvas-perf/canvas.html:
  1. Change the various tests to get the image data for the result
     to help ensure that the operation has completed by the time,
     and subtract out the time needed to do this.
  2. Made the test more flexible about number of repetitions and
     image size.
  3. Make the tests run separately and have a pause between them
     to allow for garbage collection so that results are more
     consistent.
  4. Added a standard logging function and shouldBe asserts to
     verify that the correct scaling operations were happening.

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

WebKitSite/ChangeLog
WebKitSite/demos/canvas-perf/canvas.html

index d4e3aec..f4dab51 100644 (file)
@@ -1,3 +1,22 @@
+2010-05-24  David Levin  <levin@chromium.org>
+
+        Reviewed by Maciej Stachowiak.
+
+        Improve canvas perf test accuracy.
+        https://bugs.webkit.org/show_bug.cgi?id=39635
+
+        * demos/canvas-perf/canvas.html:
+          1. Change the various tests to get the image data for the result
+             to help ensure that the operation has completed by the time,
+             and subtract out the time needed to do this.
+          2. Made the test more flexible about number of repetitions and
+             image size.
+          3. Make the tests run separately and have a pause between them
+             to allow for garbage collection so that results are more
+             consistent.
+          4. Added a standard logging function and shouldBe asserts to
+             verify that the correct scaling operations were happening.
+
 2010-05-20  Daniel Bates  <dbates@rim.com>
 
         Rubber-stamped by Simon Fraser.
 2010-05-20  Daniel Bates  <dbates@rim.com>
 
         Rubber-stamped by Simon Fraser.
index 39823f4..9f57eb7 100644 (file)
 <pre id="output">
 </pre>
 <img src="kraken.jpg" id="image">
 <pre id="output">
 </pre>
 <img src="kraken.jpg" id="image">
-<canvas id="original" width=3264 height=2448 style="width: 3264px; height: 2448px"></canvas>
-<canvas id="copy" width=3264 height=2448 style="width: 3264px; height: 2448px"></canvas>
-<canvas id="scaledUp" width=6528 height=4896 style="width: 6528px; height: 4896px"></canvas>
-<canvas id="scaledDown" width=1632 height=1224 style="width: 1632px; height: 1224px"></canvas>
-<canvas id="rotated" width=2448 height=3264 style="width: 2448px; height: 3264px; border: 1px solid red;"></canvas>
+<canvas id="original" style="width: 3264px; height: 2448px"></canvas>
+<canvas id="copy" style="width: 3264px; height: 2448px"></canvas>
+<canvas id="indirectCopy" style="width: 3264px; height: 2448px"></canvas>
+<canvas id="scaledUp" style="width: 6528px; height: 4896px"></canvas>
+<canvas id="scaledDown" style="width: 1632px; height: 1224px"></canvas>
+<canvas id="rotated" style="width: 2448px; height: 3264px; border: 1px solid red;"></canvas>
 <script>
 <script>
-function doTest() {
-    var output = document.getElementById("output");
-    var image =  document.getElementById("image");
-    var original =  document.getElementById("original");
+var width = 3264;
+var height = 2448;
+var original = document.getElementById("original");
+var originalContext = original.getContext("2d");
+var idleTimer = 20;
 
 
-    var copy =  document.getElementById("copy");
-    var scaledUp =  document.getElementById("scaledUp");
-    var scaledDown =  document.getElementById("scaledDown");
-    var rotated = document.getElementById("rotated");
+function log(text) {
+    if (typeof text != "string" )
+        text = text.toString();
+    var span = document.createElement("span");
+    document.getElementById("output").appendChild(span);
+    span.innerHTML = text.replace(/</g, "&lt;").replace("/>/g", "&gt;").replace("/&/g", "&amp")+ "<br>";
+}
 
 
-    original.getContext("2d").drawImage(image, 0, 0);
+function shouldBe(_a, _b) {
+    if (typeof _a != "string" || typeof _b != "string")
+        log("WARNING: shouldBe() expects string arguments.");
+    var _aValue = eval(_a);
+    var _bValue = eval(_b);
+    if (_aValue !== _bValue)
+        log("FAILURE: " + _a + "should have been " + _bValue + ". Instead it was " + _aValue + ".");
+}
 
 
-    var copyContext = copy.getContext("2d");
-    var originalContext = original.getContext("2d");
-    var scaledUpContext = scaledUp.getContext("2d");
-    var scaledDownContext = scaledDown.getContext("2d");
-    var rotatedContext = rotated.getContext("2d");
+function flushOperation(context) {
+   var imageData = context.getImageData(0, 0, context.canvas.width, context.canvas.height);
+}
 
 
+function timeCanvasOperation(context, canvasOperation) {
+    var repetitions = 2;
     var startDate = new Date();
     var startDate = new Date();
-    
-    copyContext.globalCompositeOperation = "copy";
-    for (var i = 0; i < 2; ++i) {
-        copyContext.drawImage(original, 0, 0);
+
+    for (var i = 0; i < repetitions; ++i) {
+        canvasOperation();
+        flushOperation(context);
     }
     }
+    var finishDate = new Date();
+    var timeWithOverhead = finishDate - startDate;
 
 
-    var time = (new Date()) - startDate;
-    output.innerHTML += "Direct image copy: " + (time/2) + "ms<br>";
+    for (var i = 0; i < repetitions; ++i) {
+        flushOperation(context);
+    }
+    var overheadTime = new Date() - finishDate;
+    return (timeWithOverhead - overheadTime) / repetitions;
+}
 
 
-    startDate = new Date();
+function doTest() {
+    var image =  document.getElementById("image");
+    image.width = width;
+    image.height = height;
     
     
-    for (var i = 0; i < 2; ++i) {
-        var imageData = originalContext.getImageData(0, 0, 3264, 2448);
-        copyContext.putImageData(imageData, 0, 0);
-    }
+    original.width = width;
+    original.height = height;
+    original.getContext("2d").drawImage(image, 0, 0);
+    window.setTimeout(doCopy, idleTimer);
+}
 
 
-    time = (new Date()) - startDate;
-    output.innerHTML += "Indirect copy with (via ImageData): " + (time/2) + "ms<br>";
+function doCopy() {
+    var copy =  document.getElementById("copy");
+    copy.width = width;
+    copy.height = height;
+    var copyContext = copy.getContext("2d");
+    copyContext.globalCompositeOperation = "copy";
+    var time = timeCanvasOperation(copyContext,
+        function () {
+            copyContext.drawImage(original, 0, 0);
+        });
+    log("Direct image copy: " + time + "ms");
+    window.setTimeout(doIndirectCopy, idleTimer);
+}
 
 
-    startDate = new Date();
-    
-    scaledUpContext.globalCompositeOperation = "copy";
-    for (var i = 0; i < 2; ++i) {
-        scaledUpContext.drawImage(original, 0, 0, 6528, 4896);
-    }
+function doIndirectCopy() {
+    var indirectCopy =  document.getElementById("indirectCopy");
+    indirectCopy.width = width;
+    indirectCopy.height = height;
+    var indirectCopyContext = indirectCopy.getContext("2d");
+    indirectCopyContext.globalCompositeOperation = "copy";
+    time = timeCanvasOperation(indirectCopyContext,
+        function () {
+            var imageData = originalContext.getImageData(0, 0, width, height);
+            indirectCopyContext.putImageData(imageData, 0, 0);
+        });
+    log("Indirect copy with (via ImageData): " + time + "ms");
+    window.setTimeout(doScaleUp, idleTimer);
+}
 
 
-    time = (new Date()) - startDate;
-    output.innerHTML += "Copy with 2x scale: " + (time/2) + "ms<br>";
+function doScaleUp() {
+    var scaledUp =  document.getElementById("scaledUp");
+    scaledUp.width = width * 2;
+    scaledUp.height = height * 2;
+    var scaledUpContext = scaledUp.getContext("2d");
+    scaledUpContext.globalCompositeOperation = "copy";
+    time = timeCanvasOperation(scaledUpContext,
+        function () {
+            scaledUpContext.drawImage(original, 0, 0, width * 2, height * 2);
+        });
+    log("Copy with 2x scale: " + time + "ms");
+    shouldBe("document.getElementById('scaledUp').width", "width * 2");
+    shouldBe("document.getElementById('scaledUp').height", "height * 2");
+    window.setTimeout(doScaleDown, idleTimer);
+}
 
 
-    startDate = new Date();
+function doScaleDown() {
+    var scaledDown =  document.getElementById("scaledDown");
+    scaledDown.width = width / 2;
+    scaledDown.height = height / 2;
+    var scaledDownContext = scaledDown.getContext("2d");
     scaledDownContext.globalCompositeOperation = "copy";
     scaledDownContext.globalCompositeOperation = "copy";
-    for (var i = 0; i < 2; ++i) {
-        scaledDownContext.drawImage(original, 0, 0, 1632, 1224);
-    }
-
-    time = (new Date()) - startDate;
-    output.innerHTML += "Copy with 0.5x scale: " + (time/2) + "ms<br>";
+    time = timeCanvasOperation(scaledDownContext,
+        function () {
+            scaledDownContext.drawImage(original, 0, 0, width / 2, height / 2);
+        });
+    log("Copy with 0.5x scale: " + time + "ms");
+    shouldBe("document.getElementById('scaledDown').width", "width / 2");
+    shouldBe("document.getElementById('scaledDown').height", "height / 2");
+    window.setTimeout(doRotation, idleTimer);
+}
 
 
-    startDate = new Date();
+function doRotation() {
+    var rotated = document.getElementById("rotated");
+    rotated.width = height;
+    rotated.height = width;
+    var rotatedContext = rotated.getContext("2d");
     rotatedContext.globalCompositeOperation = "copy";
     rotatedContext.rotate(Math.PI / 2);
 
     rotatedContext.globalCompositeOperation = "copy";
     rotatedContext.rotate(Math.PI / 2);
 
-    for (var i = 0; i < 2; ++i) {
-        rotatedContext.drawImage(original, 0, -original.height);
-    }
-
-    time = (new Date()) - startDate;
-    output.innerHTML += "Copy with rotate:" + (time/2) + "ms<br>";
+    time = timeCanvasOperation(rotatedContext,
+        function () {
+            rotatedContext.drawImage(original, 0, -original.height);
+        });
+    log("Copy with rotate: " + time + "ms");
+    shouldBe("document.getElementById('rotated').width", "height");
+    shouldBe("document.getElementById('rotated').height", "width");
+    log("DONE!");
 }
 </script>
 
 }
 </script>