Friday, November 20th, 2009

Full Frontal ’09: Jake Archibald on Performance Optimisation

Category: Performance

<p>Jake explains no-one likes waiting, and people are multi-threaded (except when they have to sneeze). Yet, we’re stuck with a single-threaded language for the most part; and we still face the legacy of a DOM standard from another era (DOM Level 1 – 1997). This talk provides some optimisation tips, backed by Jake’s cross-browser experiments.

Jake’s slides and research are online.

Optimise Where it Matters

Jake explains the importance of speeding things up where it really matters.

Doug Crockford has pointed out that in Javascript, bitwise operations aren’t close to the hardware, which stands in contrast to other languages. In fact, if you look at it, bitwise operations can still be faster than alternative operations; Jake shows an example where bitwise parsing of hex codes is faster than bitwise. The question is, how much faster? In many cases, such as this example, your energy is better spent on optimising big things.

Avoid eval() Where Possible

Jake says avoid eval() where possible. Thinking about what functions eval, here’s a brain teaser: what will the following output?

javascript
< view plain text >
  1. var msg = "spatchcock";
  2. function doStuff() {
  3.   alert(msg);
  4.   if (false) {
  5.     var msg="spotted dick";
  6.   }
  7. }
  8. doStuff();

Wait for it … the answer is “undefined”. Javascript does look ahead and create space for the local variable. So during the running of the function, there’s no need to allocate space for the variable and the browser can optimise for that, but if you use “eval”, the optimisation goes away. So avoid eval().

Prefer innerHTML to DOM

Jake shows a comparison of innerHTML versus DOM Level 1. In IE, DOM manipulation is much slower, because of the sync process between the two. The differential gets even worse when creating elements. Webkit has optimised sync between HTML and DOM, hence less difference, so it’s not as bad, but create example is still slower with DOM. So from a performance perspective, best practice is construct the HTML and use innerHTML.

Selectors

It’s educational to look at the implementation of selector libraries. Jake shows a comparison – IE7 is vastly more slow in this case. It doesn’t support getElementsByClassName, querySelectorAll, evaluate; and it does support getElementById, but that’s not used by sizzle for this query. So getElementsByTagName is all that’s left; and if you knew that, and the implications, you could have made the query much faster.

Benchmarking

Pretty simple.

javascript
< view plain text >
  1. var duration;
  2. start = new Date()
  3. thingToTest();
  4. duration = new Date() - start;

However, timing isn’t so accurate, so stick it in a function and run it many times.

Too easy … so go benchmark and report your findings.

Related Content:

Posted by Michael Mahemoff at 12:11 pm
13 Comments

++++-
4 rating from 25 votes

13 Comments »

Comments feed TrackBack URI

Sad to see, that innerHTML is still faster. Sure, often its more easier. But DOM is safer to create valid & working content in webapps.

Comment by gabel — November 20, 2009

what an odd bit of example code, heh.

Comment by jonhartmann — November 20, 2009

in the first code example, I think there should actually be a call to doStuff() at the end

Comment by heswell — November 20, 2009

Really interesting articles. There’s been a change for the worse in the writing style recently however – it looks like the notes are being taken down as the speakers are talking, which is fine if that’s the case. Will it return to normal for other articles though? As an example, a paragraph such as

“Doug Crockford has pointed out that in Javascript, bitwise operations aren’t close to the hardware, which stands in contrast to other languages. In fact, if you look at it, bitwise operations can still be faster than alternative operations; Jake shows an example where bitwise parsing of hex codes is faster than bitwise. The question is, how much faster. In many cases, such as this example, you’re energy is better spent on optimising big things.”

is actually quite hard to understand and it’s not just the fact that “you’re” should be “your” and there’s a question mark missing. Perhaps a quick post-edit would be some help?

Comment by okohll — November 20, 2009

@okohll, thanks I’ve fixed that. The notes from Full Frontal today were indeed being live blogged under a less-than-ideal 3G (in theory only) connection, which made post-editing something of a challenge at times.

Comment by Michael Mahemoff — November 20, 2009

I think DOM test results would be more interesting if there was only one execution of “container.appendChild(bufferDiv);” as innerHTML do (container.innerHTML = str;).

Comment by checkca — November 21, 2009

@checkca

Added a couple of variations on the DOM level 1 methods, including one that only does 1 append to container. It’s faster in Firefox but slower in IE, but the differences are minor.

Very interesting to run the tests before & after opening the web inspector in webkit.

Comment by jaffathecake — November 21, 2009

Oops, forgot to add a url for those: http://www.jakearchibald.co.uk/jsperformance/creatingelements/

Comment by jaffathecake — November 21, 2009

@jaffathecake

When I use document.createElement(‘div’) instead of document.createDocumentFragment(), it gives me the best results on Chrome. I know it’s not exactly the same test as I add one more container DIV but it’s quite interesting.

3725ms – Dom Level 1 Method with Div Buffer
6834ms – Dom Level 1 Method with DocumentFragment

Comment by checkca — November 21, 2009

Have you opened the web inspector while you run that test? I only get figures like those if I’ve opened the inspector (which slows down the page and skews results).

Without web inspector:
~350ms – Dom Level 1 Method with DocumentFragment
~350ms – Dom Level 1 Method with div container

With web inspector open:
~1300ms – Dom Level 1 Method with DocumentFragment
~800ms – Dom Level 1 Method with div container

(results fluctuate wildly for this test on chrome, so the above is approxomate)

Comment by jaffathecake — November 21, 2009

It’s weird… My Chrome (4.0.249.4) doesn’t have the same behaviour. When I close Chrome and reopens it without opening Web Inspector, I get those results :
div container ~= 800ms
doc fragment ~= 1400ms

With FireFox without firebug active, I get :
div container ~= 2500ms
doc fragment ~= 3400ms

IE8 takes ~= 5400ms (and ~= 1500ms with innerHTML), I hope MS will fix that in IE9 :p.

Comment by checkca — November 21, 2009

I imagine Chrome 4 is running with significant amounts of debug code enabled. My results are from Chrome 3.

Comment by jaffathecake — November 21, 2009

Very interesting. I can’t find any audio to accompany the slides. Is it published anywhere?

Comment by ExtAnimal — November 25, 2009

Leave a comment

You must be logged in to post a comment.