I've been working with a company called Catchpoint to hash out some inconsistencies in our client-side code metrics. They have some events that fire which measure milestones in the page load process. Their provided metrics for us is in IE8.
Now, they claim that the way JQuery determines DOM ready in IE actually drastically hurts page performance and that we should avoid it at all costs. I'm aware of what JQuery does with the doScrollCheck()
method and the 1ms recursive setTimeout
blast on documentElement
and it occurred to me that they may have a valid claim.
They said performance is hurt exponentially for every $(document).ready()
block.
My question is, are their any stats out there to validate this claim, and if so, how would I go about implementing an IE-friendly solution without re-writing the JQuery source for my needs.
According to JSperf, multiple DOM ready functions really do slow down the page in all browsers, enough so that I will be refactoring a lot of my own code to accommodate for this new finding. IE is embarrassingly slower, of course, but the test isn't as informative as I'd hoped because it's so much slower even with no DOM ready check. The thing to take away from this is to minimize the use of these DOM ready functions whenever possible.
Results in Chrome:
- Single $(document).ready(): 734,811 ops/sec
- Multiple $(document).ready()'s [4 blocks]: 151,989 ops/sec
- No $(document).ready(): 208,965,555 ops/sec
Results in IE8:
- Single $(document).ready(): 26,349 ops/sec
- Multiple $(document).ready()'s [4 blocks]: 5,971 ops/sec
- No $(document).ready(): 5,000,159 ops/sec
Analyzing these metrics:
- In Chrome, No DOM ready check takes 0.35% of the time a DOM ready
check takes
- In IE, No DOM ready check takes 0.53% of the time a DOM
ready check takes
That data alone tells us that the doScrollCheck()
function deters performance quite a bit.
That being said:
- Chrome's DOM ready check is 27.98 times faster than IE's
- On Chrome, doing 4 DOM ready checks is 25.45 times faster than on IE
- The absence of a DOM ready check is 41.79 times faster on Chrome than IE
On the surface, this looks hopeless - but if you think about it, the IE page with no DOM ready function was executing over 5 million ops/sec and the single DOM ready function on Chrome was executing less than a million. That tells me if you manage to tell JQuery to use a more friendly doScrollCheck()
function which, say checks if documentElement
is scrollable every 100ms instead of every 1ms you might see the page load time more competitive with chrome.
What this benchmark really tells me is that even the DOMContentLoaded
check is slow as hell - there's no excuse to go from 209 million ops/sec to under a million on Chrome.
http://jsperf.com/docready/3
Here's a script that measures the time between $(document).ready()
firing and code executing at the end of the body (which is the earliest possible time that you can manipulate the DOM). You can run it yourself in whatever browsers you want. The page is here: http://jsfiddle.net/jfriend00/dLx4L/.
I've done this one in jsFiddle for convenience, longevity and ease of sharing, but you could probably make a more accurate test if you made a standalone webpage that implemented this same technique (no other frames involved like in the jsFiddle). In any case, you should be able to get the idea here how you could measure this and put real numbers to it.
My 2c:
I have seen a lot of web developers put ten million javascript code in the page ... along with the last being the document-ready.
a) Bare in mind that NO USER will, in a perfect world, interact with the web page as soon as it loads (shown); and
b) Still in the perfect world, the user will, most likely, look at the entire page before (even scrolling up and down) making any interaction.
With that perfect scenario in mind, all you should have between the < script type ... >< /script> is the miniminum necessary for the SPLASH of the page and, of course, the document-ready.
Here comes the magic: PUT EVERYTHING ELSE IN A SEPARATE SCRIPT.JS file and load it with getScript in the document-ready:
$(document).ready( function () {
...
...
$.getScript('your-scripts-path/your-script-file-name.js');
});
Bare in mind that the $.getScript can, of course, become a callback within one of the dom-ready calls. And, it too, can have callbacks.
Good luck!