putImageData vs drawImage (complicated canvas)

JavaScript performance comparison

Test case created by Rob and last updated

Info

I'm not drawing sprites, I'm drawing graphs and then animating them. As such I am rendering to a hidden canvas and pasting it into a visible one.

It seems like putImageData is faster when I run CPU profiles but everything on the internet indicates that drawImage is faster.

Preparation code

<script type="text/javascript">
    document.write("\<script src='http://code.jquery.com/jquery-latest.min.js' type='text/javascript'>\<\/script>");
</script>
<div>
<h1>Hidden Canvases</h1>
<canvas width=800 height=100 id="hide1" style="display:none"></canvas>
<canvas width=400 height=100 id="hide2" style="display:none"></canvas>
<h1>More Hidden</h1>
<canvas width=200 height=100 id="hide3" style="display:none"></canvas>
<canvas width=200 height=100 id="hide4" style="display:none"></canvas>
<h1>Canvas 1 (visible)</h1>
<canvas width=800 height=100 id="c1"></canvas>
<h1>Canvas 2 </h1>
<canvas width=800 height=100 id="c2"></canvas>
<h1>Canvas 3 </h1>
<canvas width=400 height=100 id="c3"></canvas>
<h1>Canvas 4 </h1>
<canvas width=400 height=100 id="c4"></canvas>
<h1>Canvas 5 </h1>
<canvas width=800 height=100 id="c5"></canvas>
</div>
<script>
Benchmark.prototype.setup = function() {
    function lookup(val) {
      if (val == 0)
        return "#0000d4";
      else if (val == 1)
        return "#00496d";
      else if (val == 2)
        return "#ff2400";
      else if (val == 3)
        return "55aa00";
      return "ffffff";
    }
   
    //generate data
    var width = 400;
    var data_width = 400;
    var data = [];
   
    function setup_data() {
      for (var i = 0; i < data_width; i++) {
        data[i] = [];
        for (var j = 0; j < 100; j++) {
          data[i][j] = Math.floor(Math.random() * 5)
        }
      }
    }
   
    function draw_hidden(ctx,a,b) {
      var lim = (b - a) || width
      for (var x = 0; x < lim; x++) {
        for (var y = 0; y < 100; y++) {
          ctx.beginPath();
          ctx.moveTo(x, y);
          ctx.strokeStyle = lookup(data[(x + a) || x][y]);
          ctx.lineTo(x + 1, y);
          ctx.lineWidth = 1;
          ctx.stroke();
        }
      }
    }
   
    setup_data();
   
    var hide1 = $("#hide1")[0];
    var hide2 = $("#hide2")[0];
    var hide3 = $("#hide3")[0];
    var hide4 = $("#hide4")[0];
   
    var hide1_ctx = hide1.getContext('2d');
    var hide2_ctx = hide2.getContext('2d');
    var hide3_ctx = hide3.getContext('2d');
    var hide4_ctx = hide4.getContext('2d');
   
    var c1 = $("#c1")[0];
    var c2 = $("#c2")[0];
    var c3 = $("#c3")[0];
    var c4 = $("#c4")[0];
    var c5 = $("#c5")[0];
   
    var c1_ctx = c1.getContext('2d');
    var c2_ctx = c2.getContext('2d');
    var c3_ctx = c3.getContext('2d');
    var c4_ctx = c4.getContext('2d');
    var c5_ctx = c5.getContext('2d');
};

Benchmark.prototype.teardown = function() {
    //hide1_ctx.clearRect(0,0,600,100);
    //hide2_ctx.clearRect(0,0,100,100);
    //c1_ctx.clearRect(0,0,600,100);
    //c2_ctx.clearRect(0,0,600,100);
    //c3_ctx.clearRect(0,0,600,100);
   
};
</script>

Preparation code output

Hidden Canvases

More Hidden

Canvas 1 (visible)

Canvas 2

Canvas 3

Canvas 4

Canvas 5

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
putImageData
draw_hidden(hide1_ctx);
c1_ctx.putImageData(hide1_ctx.getImageData(0, 0, width, 100), 0, 0);
pending…
drawImage
draw_hidden(hide1_ctx);
c2_ctx.drawImage(hide1, 0, 0, width, 100, 0, 0, width, 100);
pending…
200x100 putImage
draw_hidden(hide2_ctx);
c1_ctx.putImageData(hide2_ctx.getImageData(0, 0, width, 100), 0, 0);
pending…
200x100 drawImage
draw_hidden(hide2_ctx);
c2_ctx.drawImage(hide2, 0, 0, width, 100, 0, 0, width, 100);
pending…
100x100 src dst putImage
draw_hidden(hide2_ctx);
c3_ctx.putImageData(hide2_ctx.getImageData(0, 0, width, 100), 0, 0);
pending…
100x100 src dst drawImage
draw_hidden(hide2_ctx);
c3_ctx.drawImage(hide2, 0, 0, width, 100, 0, 0, width, 100);
pending…
2x 50x100 src dst
draw_hidden(hide3_ctx, 0, width/2);
draw_hidden(hide4_ctx, width/2, width);
c4_ctx.drawImage(hide3, 0, 0, width/2, 100, 0, 0, width/2, 100);
c4_ctx.drawImage(hide4, 0, 0, width/2, 100, width/2, 0, width/2, 100);
pending…
raw draw
draw_hidden(c4_ctx);
pending…
raw draw (large canvas)
draw_hidden(c5_ctx);
 
pending…

Compare results of other browsers

Revisions

You can edit these tests or add even more tests to this page by appending /edit to the URL. Here’s a list of current revisions for this page:

0 comments

Add a comment