Just for fun I wrote this little benchmark to measure the rendering performance of current browsers in terms of DOM updates.
Have a look at the screenshot:
The screen consists of about 4000 tiny (16×16 pixel) DIVs, using an absolute layout (CSS-wise). So every DIV has a fixed position, the first div’s position is (0,0), the second div’s position is (16,0), the 3rd (32,0) etc.
1. First I will redraw these 4000 DIV 10 times, and print the average DIVs/s after these 10 times. On my laptop I got about 20,000 DIVs/s on Chrome, Firefox and IE11.
On my desktop I reached up to 100,000 DIVs/s. Chrome was ahead in this benchmark, but only with a small margin.
Technically I will delete all 4000 DIVs and recreate those DIVs again, updating the DOM only once, just like that:
$("#wrapper").empty();
var divs = "<div style='color: #000000'></div>" +
"</div></div>" +
"</div></div>";
// and 4000 DIVs more
$("#wrapper")[0].innerHTML = divs;
2. Then I will update all DIVs (not recreating them) and will measure the distance to your current mouse position. You know, our old Pythagoras: dist = sqr(x^2+y^2).
So it will look like that:
Wow, Chrome is insanely fast here. In comparison to IE and Firefox, I guess, it’s at least 3 times faster.
One side note:
On the opening screen you will see a ‘watermark’ of Triona. How is that done?
With HTML5 you have a canvas and inside that canvas you can draw images. This image you can read pixel by pixel. So I reproduce this image by reading its pixel information and recreate it using those 16×16 boxes. Furthermore I did some color effect to make it look nicer.
On the HTML page I have our Triona logo (it’s base64 encoded):
<img id=”imgTriona” alt=”Triona” src=”image/png;base64,iVBORw0K…” />
In Javascript I read this picture into a 2-dimensional array:
function getImgData(img) {
var imgWidth = img.width, imgHeight = img.height;
var ctx = $("#myCanvas")[0].getContext("2d");
ctx.drawImage(img, 0, 0);
var imgDataOrigin = ctx.getImageData(0, 0, imgWidth, imgHeight);
return imgDataOrigin;
}
Now I have an array containing pixel information in this format:
[r(0,0),g(0,0),b(0,0),a(0,0)],
[r(0,1),g(0,1),b(0,1),a(0,1)],
…
[r(x,y),g(x,y),b(x,y),a(x,y)],
and then I recreate that image using the 16×16 boxes.
function drawImgWatermark(imgDataOrigin, imgWidth, imgHeight) {
var divs = $("#wrapper div");
var xOffset = divWidth > imgWidth ? parseInt((divWidth - imgWidth) / 2) : 0;
var yOffset = divHeight - imgHeight;
for (var y = 0, imgIdx = 0; y < imgHeight; y++) {
for (var x = 0; x < imgWidth; x++, imgIdx += 4) {
var r = imgDataOrigin.data[imgIdx];
if (r < 60) continue;
var divIdx = (y + yOffset) * divWidth + x + xOffset;
var div = divs[divIdx];
var rgbDiv = readColor(div.style.backgroundColor);
var r1 = parseInt(x = imgWidth / 2 ? rgbDiv[1] ^ 255 : rgbDiv[1] * 1.5),
b1 = parseInt(rgbDiv[2] * 1.5);
divs[divIdx].style.backgroundColor = "rgb(" + r1 + "," + g1 + "," + b1 + ")";
}
}
$("#wrapper").append(divs);
}
Looks a little bit complicated, but in fact, it’s not 😉 I’m just XORing the current red or green parts, when the pixel in our logo is bright enough:
var r = imgDataOrigin.data[imgIdx];
if (r < 60) continue;
// change the DIVs background color
Try it on your favourite browsers. On your laptop, on your desktop. Perhaps it even runs on a tablet – haven’t tried it though.
Have fun.
BTW, in 7 hours we have the year 2015. Happy new year. Last blog article this year.