<canvas id="c" width="800" height="600"></canvas>
$c = document.getElementById('c');
$ctx = $c.getContext('2d');
$ctx.clearRect(0, 0, 800, 300);
$px = $ctx.createImageData(1, 1);
$id = $ctx.getImageData(0, 0, 800, 600);
$pxls = [];
for (var i = 0; i < 1000000; ++i) {
const pxl = {
x: Math.random() * 800 << 0,
y: Math.random() * 300 << 0,
r: Math.random() * 255 << 0,
g: Math.random() * 255 << 0,
b: Math.random() * 255 << 0,
a: Math.random() * 128 << 0 + 128
};
pxl.rgba = [pxl.r, pxl.g, pxl.b, pxl.a];
$pxls.push(pxl);
};
$i = 0;
$iterations = 5000;
/*
At 1500+ $iterations the putimagedata/getimagedata starts to win and at 5000 it slaughters. Below that the other methods win
So it depends on how many you plan on drawing each frame
*/
for (var i=$iterations;i--;){
var px = $pxls[$i++ % 10000];
$ctx.fillStyle = 'rgba(' + px.r + ',' + px.g + ',' + px.b + ',' + (px.a / 255) + ')';
$ctx.fillRect(px.x, px.y, 1, 1);
}
for (var i=$iterations;i--;){
var px = $pxls[$i++ % 10000];
$ctx.fillStyle = 'rgba(' + [px.r,px.g,px.b,px.a/255].join() + ')';
$ctx.fillRect(px.x, px.y, 1, 1);
}
for (var i=$iterations;i--;){
var px=$pxls[$i++ % 10000], d=$px.data;
d[0] = px.r;
d[1] = px.g;
d[2] = px.b;
d[3] = px.a;
$ctx.putImageData($px, px.x, px.y);
}
for (var i=$iterations;i--;){
var px = $pxls[$i++ % 10000];
$ctx.fillStyle = `rgba(${px.r},${px.g},${px.b},${px.a/255}})`;
$ctx.fillRect(px.x, px.y, 1, 1);
}
var canvasWidth = $c.width;
var canvasHeight = $c.height;
var id = $ctx.getImageData(0, 0, canvasWidth, canvasHeight);
var pixels = id.data;
for (var i=$iterations;i--;){
var px = $pxls[$i++ % 10000];
var off = (px.y * canvasWidth + px.x) * 4;
pixels[off] = px.r;
pixels[off + 1] = px.g;
pixels[off + 2] = px.b;
pixels[off + 3] = px.a;
}
$ctx.putImageData(id, 0, 0);
var canvasWidth = $c.width;
var canvasHeight = $c.height;
var id = $ctx.getImageData(0, 0, canvasWidth, canvasHeight);
var pixels = id.data;
for (var i=$iterations;i--;){
var px = $pxls[$i++ % 10000];
var off = (px.y * canvasWidth + px.x) * 4;
pixels.set(px.rgba,off);
}
$ctx.putImageData(id, 0, 0);
var canvasWidth = $c.width;
var canvasHeight = $c.height;
var id = $ctx.getImageData(0, 0, canvasWidth, canvasHeight);
var pixels = id.data;
for (var i=$iterations;i--;){
var px = $pxls[$i++ % 10000];
var off = (px.y * canvasWidth + px.x) * 4;
pixels.set([px.r,px.g,px.b,px.a],off);
}
$ctx.putImageData(id, 0, 0);
var canvasWidth = $c.width;
var canvasHeight = $c.height;
//var id = $ctx.getImageData(0, 0, canvasWidth, canvasHeight);
var pixels = $id.data;
pixels.fill();
for (var i=$iterations;i--;){
var px = $pxls[$i++ % 10000];
var off = (px.y * canvasWidth + px.x) * 4;
pixels.set(px.rgba,off);
}
$ctx.putImageData($id, 0, 0);
--enable-precise-memory-info
flag.
Test case name | Result |
---|---|
fillRect/concat | |
fillRect/join | |
1×1 Image Data | |
fillRect/template literal | |
getImageData/putImageData | |
getImageData/putImageData - set px.rgba | |
getImageData/putImageData - set [px.r, px.g, px.b, px.a] | |
getImageData/putImageData - set - no getImageData |
Test name | Executions per second |
---|---|
fillRect/concat | 188.4 Ops/sec |
fillRect/join | 200.2 Ops/sec |
1×1 Image Data | 4.3 Ops/sec |
fillRect/template literal | 5.7 Ops/sec |
getImageData/putImageData | 302.4 Ops/sec |
getImageData/putImageData - set px.rgba | 281.4 Ops/sec |
getImageData/putImageData - set [px.r, px.g, px.b, px.a] | 276.8 Ops/sec |
getImageData/putImageData - set - no getImageData | 649.8 Ops/sec |
I'd be happy to help you understand the benchmark results!
The benchmark results are for various tests related to image data and drawing on canvas elements in Firefox 132, running on Linux.
Here are some observations and insights from the results:
px.rgba
) or using arrays of individual color components ([px.r, px.g, px.b, px.a]
). These variations likely reflect different approaches to optimizing performance.getImageData
is not used before calling putImageData
. It's possible that this test is designed to isolate the impact of using putImageData
without first fetching image data from a canvas.fillRect
method. This could be due to a specific quirk in Firefox's JavaScript engine or a limitation in the language itself.Overall, these results provide insights into the relative efficiency of different approaches to drawing and manipulating canvas elements in Firefox 132.