Speed up your JavaScript: The talk

Steve Souders recently invited me to participate in his Web Exponents speaker series at Google. Periodically, people come in to give hour-long tech talks about various topics. Since I had most recently worked with Steve on his new book, Even Faster Web Sites. I wrote a chapter on JavaScript performance, and Steve asked if I would come and share some tips along those lines to the folks at Google. In following along my series of blog posts about JavaScript performance, I entitled this talk, Speed up your JavaScript.

The talk today went very well (aside from some humorous technical glitches). Attendance was good and there were a lot of good, insightful questions both during the presentation and afterwards. My slides are available now and there will be a video coming out possibly next week. Topics include how to optimize:

  • Scope management
  • Data access
  • Loops
  • DOM

After the talk, I went to lunch with Steve and Doug Crockford (who attended the talk as well) for a little more discussion about the state of web technology. Overall, a very fun experience.

One of the biggest points I want to make about this talk, both for those who were there and those who were not, is that I’m not saying to do things all the time. The techniques presented in the talk are intended as a guide for those who have noticed performance bottlenecks and need to know how to fix them. Optimization without measurement is fruitless, and I’d be doing everyone a great disservice by presenting these techniques as “must follow” under any and all circumstances. Always measure the performance of your code using a profiler (shameless plug: YUI Profiler is pretty sweet) and then determine what you should do to speed things up.

Doug pointed out to me afterwards that he thought a lot of the early topics in the talk generally don’t provide a big performance gain. I think his statement has some validity, as everything is related to the code base in which you’re developing. When I worked on My Yahoo!, we had a lot of trouble with loop performance and did a lot of optimizations for it. Others might not have bottlenecks around their loops. All of the information in my talk is based on performance issues I’ve faced in my career, and though some may be obscure, I believe it’s important to talk about those issues so they can be a guide for others who find bottlenecks in these areas. The worst thing we can do is avoid coming up with solutions for rare problems, because rare problems need solving too.

After the talk, we ran into Mark Miller, the research scientist at Google behind Caja. He hadn’t seen the talk but word of its topics apparently traveled quickly to him. He mentioned that it seemed like my talk was geared at programming in poorly-performing browsers. That’s entirely true, my talk is geared towards those poor souls (along with myself) who are stuck developing for Internet Explorer, Firefox, Safari, and Opera. Those with the luxury of only developing for Chrome or any other browser using a JIT JavaScript compiler don’t need to worry about performance issues (so far). Mark seemed to be concerned about my recommendation to avoid using the native forEach() method (as defined in ECMA-262, 5th Edition). In my talk, I stated that this implementation is much slower than using a regular JavaScript loop, which is true (it’s very much slower). This is true in Firefox and Chrome, both of which have implemented the method natively. Mark asserted that ECMAScript 5 won’t be implemented in anything but the most performant JavaScript engines, which would use inlining to improve performance. Though good to hear, it made me realize that I should have explained more completely the purpose of this talk: to help developers who are dealing with crappy browser performance right now.

The experiments I ran for the talk (and mentioned in the video) are here:

You may not use everything in this talk, and that’s fine. I do hope you’ll keep this information in the back of your mind and return to it should you notice performance issues in your JavaScript. I’ve been in situations where milliseconds were being counted under close scrutiny, and I hope that this information will help developers who are in a similiar situation.

Comments

  1. razvantim

    Very interesting slideshow. Hope the video presentation will be out soon.

  2. Leandro

    the video is already available here: http://www.youtube.com/watc...

    excellent presentation btw!!! I'm glad I found this site!

    I understand that, for eg, yahoo mail cares about this, because there must be a huge js behind this, but I think that in almost all sites the improvement in permormance won't be noticed, as you said in this post. But this is still extreme valuable, especially for those who update and build js frameworks.

    It is very sad have to develop for IE. I think all developers should make a plot against IE. just kidding xD

  3. CJ

    I just watched that youtube video. That was an awesome presentation. I learned a lot from it.

    I have a question though, let's say i have a calendar which is a table tag, row tag, etc.. and it contains text values in it. I have a button that changes the text node values of the calendar. Does it cause a re-flow every time i change the value of a text node?

  4. Nicholas C. Zakas

    Thanks for the kind words, CJ. Changing the value of a text node in a table will, I believe, cause reflow unless you've set the table to be table-layout: fixed.

  5. Nick Tulett

    It's always worth pursuing performance gains that work - even if they seem insignificant in the single user case, all that processing time for millions of page views has to outweigh the cost of a few minute's extra thought and typing.

  6. razvantim

    I've just watched the YouTube presentation. Great presentation, clear explanation and DocumentFragment is my new hero :).

  7. Nick Tulett

    Just been reading through your PDF from Velocity and on p. 37 you give an example of caching document in a local variable. Do you happen to know if this optimisation is exploited within jQuery or YUI?

    For instance is it much better to use:

    var doc = document;
    var button1 = doc.getElementById("btn1");
    var div9 = doc.getElementById("div9");

    than

    var button1 = $("#btn1");
    var div9 = $("#div9");

    or am I just clutching at premature optimisation straws now?

  8. Nick Tulett

    Well, to answer my own question,

    function pureJS(){
    var doc = document;
    for (var i=0;i<10000;i++) {
    var button1 = doc.getElementById("btn1");
    var div9 = doc.getElementById("div9");
    };
    }

    is 20x faster than

    function jQ(){
    for(var i=0;i<10000;i++){
    var button1 = $("#btn1");
    var div9 = $("#div9");
    }
    }

    For the jQuery version, init() is called 80,000 times!

    In the single case, the difference is one sixth of a millisecond, so I can see that it might not always pay off...

  9. Nicholas C. Zakas

    @Nick - Yes, oftentimes the change in doing something a single time is so small as to not be worthwhile. The biggest changes are always realized when there are multiple operations being performed repeatedly. Also factor in that the jQuery $() function isn't simply passing through to document.getElementById(), there is some processing on the input string and other magic that happens under the covers, which is why $() will always end up being slower than document.getElementById() when compared across multiple operations.

  10. Paolo Chiodi

    What about string?
    It’s mentioned in many optimization recommendations to use array join() function instead of multiple string concatenation.

    I found in my own tests instead that the concatenation methodi is faster then array.join(). Here's my code:

    var times = 5000000;
    function run_test1()
    {
    var res = '';

    for(var i=0; i < times; i++)
    {
    res += 'abcd';
    }
    }

    function run_test2()
    {
    var res;
    var arr = [];

    for(var i=0; i < times; i++)
    {
    arr[arr.length] = 'abcd';
    }

    res = arr.join();
    }

  11. Nicholas C. Zakas

    @Paolo - join() is always faster in Internet Explorer. Other browsers have implemented improvements to string concatenation that make join() slower.

  12. David Calhoun

    @Paolo I ran some similar tests myself and was surprised to find that concatenation was actually faster than join() for small strings. My test basically compared this:

    var result = 'test' + 'test';

    To this:

    var arr = ['test', 'test'];
    var result = arr.join();

    For this very simple case scenario, the times for concatenation were definitely faster for all browsers tests I ran, as long as the strings were small enough. For IE6, the array method took 3 times longer than regular concatenation.

    It's only when I increased the string length (100 characters instead of 4) and the number of strings (10 instead of 2) where performance improvements with join() were noticed. However, even with this test, regular concatenation was still slightly faster (not 3x faster this time, but more like 1.3x faster). I'm planning on writing a little article with my results after I've finished testing everything.

Understanding JavaScript Promises E-book Cover

Demystify JavaScript promises with the e-book that explains not just concepts, but also real-world uses of promises.

Download the Free E-book!

The community edition of Understanding JavaScript Promises is a free download that arrives in minutes.