What about IE? What about Web Kit? How much difference does CSS really make?
I've divided the task into a few parts.
- Create a test harness that can measure performance speed.
- Work out some common operations and the best way of performing these operations under different CSS conditions (and therefore establish what techniques are best used to determine fastest CSS practice).
- Create some tests that measure the performance hit of some of the inefficient CSS described in the Mozilla article.
In this first blog article I will concentrate on the creating of a test harness.
A Test Harness
So, first I need an HTML page with a percentage bar, a start button and a results table.
Next I need a test function that will run a setup funcion, the actual test, clean up and give me a measurement of the time into my results table.
I return with an additional 500ms to give the browser some time to sort anything out that it needs to. My next problem is that the runTest is asynchronous - if I want to use it to run multiple tests then I could end up with some horrible test definitions. It would be nice if the tests could be defined as an array and the asynchronous nature wrapped up. To do this, I make use of a capture variable and some recursion. The function can also keep track of how many tests have been performed and update the percentage bar.
A first test
Those who have tried to use innerHTML with tables in IE have probably discovered that IE does not support innerHTML for elements in the structure of a table. So TD.innerHTML works and DIV.innerHTML = ">table... works but TABLE.innerHTML, TBODY.innerHTML, TR.innerHTML all fail in IE. They seem to strip out the table elements and add the contents of the TD to whatever table element you are altering, regardless of what is allowed, ending up with SPAN elements being the direct children of TABLE elements.
We will bypass this by sticking new table rows inside a dummy<table><tbody></tbody</table> and then extracting out the rows and moving them to our existing table - hence creating rows using innerHTML and measuring the performance with a real life hindrance.
Because the point of this is to measure the performance with relation to CSS, we will perform each test with both 25 and 625 css selectors that target things on the table. We will go into more detail on using CSS selectors in a later part, but at this point I just want to determine if a particular approach is better with lots of CSS versus not very much. I'm also going to go into some detail over the order in which elements are created and added to the DOM - do we do createElement, add it to the DOM and then set the class name or is it better to set the className and then add it to the DOM?
Mix of innerHTML and createElement
First off is an attempt that most people might go for - they know innerHTML is faster but don't want a more complex solution for the sake of speed.
Next we have a solution that does not use innerHTML at all.
And as discussed earlier in the blog our solution that just uses innerHTML to create our elements.
Mix of both - but disconnected from the DOM
Next in our first variation we take the first example but don't attach it to the DOM until after we have set properties like the className and innerHTML.
all document.createElement but disconnected from the DOM
And for comparison, our function that uses createElement, but we wait until everything is ready before attaching to the DOM.
I tested some browsers on my Windows 7 machine and a HTC Desire (Android) and here are the results.
|Css Rules||HTC Desire||Chrome||IE9 PP7||Opera||Firefox 3.6||IE8||IE8 In IE7 Mode|
|Mix of innerHTML and createElement||25||9073||778||9302||31212||4760||10773||10809|
|Mix of innerHTML and createElement||625||13159||1845||10197||34063||7381||10741||10727|
|Mix of both - but d/c from the DOM||25||1894||687||2072||378||837||2161||2357|
|Mix of both - but d/c from the DOM||625||11742||1808||2250||757||1821||2206||2417|
|all document.createElement but d/c||25||1671||622||2252||396||1314||2285||2437|
|all document.createElement but d/c||625||12386||1823||2400||830||2301||2397||2507|
I'll let you draw your own conclusions as to the gap between IE8 on a dual core windows 7 machine and WebKit on a mobile phone. I've highlighted the results that give the best performance, both with lots of css and minimal css. I've created a table (below) which is the time with the optimal time subtracted - E.g. the loss in performance from optimal if you implement a particular technique.
|Css Rules||HTC Desire||Chrome||IE9 PP7||Opera||Firefox 3.6||IE8||IE8 In IE7 Mode||Total|
|Mix of innerHTML and createElement||25||7402||156||8326||30869||3923||9575||9717||69968|
|Mix of innerHTML and createElement||625||1766||68||9087||33354||5560||9500||9560||68895|
|Mix of both - but d/c from the DOM||25||223||65||1096||35||0||963||1265||3647|
|Mix of both - but d/c from the DOM||625||349||31||1140||48||0||965||1250||3783|
|all document.createElement but d/c||25||0||0||1276||53||477||1087||1345||4238|
|all document.createElement but d/c||625||993||46||1290||121||480||1156||1340||5426|
This makes it obvious that even though it's not always the best, using innerHTML (even though we had get references afterwards and hack it in by creating a fake holding table) is faster overall.
Next Part - Sorting!