5 ms·
in your set function for canvas, you change the fill style for each set, and you draw a full rectangle which causes an invalidation event for the browser. i t
by jdavid 16y ago
in your set function for canvas, you change the fill style for each set, and you draw a full rectangle which causes an invalidation event for the browser.
i think you are taking the wrong approach.
this page shows a fast redeye removal example
http://disruptive-innovations.com/zoo/demos/eyes.html http://disruptive-innovations.com/zoo/demos/eyes.html
instead of operating on the canvas data, you should operate on the imageData object, which is like a buffer and will not cause an invalidation paint event.
original function
structs.grid_canvas = function(size) {
var canvas = document.createElement("canvas");
canvas.width = size[0];
canvas.height = size[1];
var ctx = canvas.getContext("2d");
return {
set: function(pos, value) {
ctx.fillStyle = 'rgb(' + value +',0,0)';
ctx.fillRect(pos[0], pos[1], 2, 2);
},
get: function(pos) {
return ctx.getImageData(pos[0], pos[1], 1, 1).data[0];
}
}
}
new function
structs.grid_imagedata = function(size) {
var canvas = document.createElement("canvas");
canvas.width = size[0];
canvas.height = size[1];
var ctx = canvas.getContext("2d");
var imgd = ctx.getImageData(0, 0, size[0], size[1]);
/**
//use this to invalidate the canvas at a reasonable frame_rate
var frame_rate = 24; //fps
var paint_frame = setInterval( function(){
ctx.putImageData(imgd, 0, 0);
}, 1000/frame_rate );
*/
return {
set: function(pos, value) {
var offset = (pos[1] * imgd.width + pos[0]) * 4;
// + 0=red, 1=green,2=blue,3=alpha
imgd.data[offset + 0]= value;
},
get: function(pos) {
var offset = (pos[1] * imgd.width + pos[0]) * 4;
// + 0=red, 1=green,2=blue,3=alpha
return imgd.data[offset + 0];
}
}
}
- shazow 16y agogetImageData returns an array equivalent to grid_1d_array. The computation required to translate the 2d position (in this case 3d position as there's 4 slots per index) is what killed the performance of grid_1d_array. Also I don't see how invalidating the canvas 24 times per second is going to help in this benchmark?
- bgrins 16y agoCalling fillRect is massively slower than calculating the an index in the array. As a general rule, it is more efficient to modify native data structures directly, while updating the DOM as infrequently as possible. I understand that you may have been wanting to benchmark the actual speed of updating the canvas, but it really isn't a fair comparison with updating arrays. Invalidating the canvas 24 times a second doesn't help with the benchmark, but it would make the example usable, in that it would actually update the canvas element on your screen. On my computer, the example from jdavid ran in 287ms, instead of the original which ran in 7427ms.
- shazow 16y agoI was trying to benchmark the actual speed of updating the canvas, in hopes that it was doing something clever behind the scenes. I can see that it's not a fair comparison, but a fair comparison is completely redundant with grid_array_1d (except a needlessly larger array).
- bgrins 16y agoI see your point. Thanks for posting this code - I implemented the a* pathfinding algorithm in javascript, so I looked into some of these options also. I ended up using the basic 2d structure to store the grid, since it was the most straightforward and seemed somewhat equivalent to 1d. For a demo of it (http://briangrinstead.com/files/astar/ http://briangrinstead.com/files/astar/), I used divs to represent the grid on the page, but I think it would be awesome to use the canvas grid representation since I suspect it will have much better performance than thousands of divs on the page (switch it to 100x100 to see what I mean).
- jdavid 16y agothat is arguably true, but the reality is that drawing that many rectangles is not the right way to use a drawing api. i am actually really shocked that i could not find a way to do all of the draw operations on a buffer.
- thegoleffect 16y agoIs there a place I can go to find out more information like this?