JavaScript loop performance

When developing JavaScript, performance is one of the vital things. Therefore, I thought I’d share the performance of loops with JavaScript, and give some advice.

Three different loop approaches

Loop 1

The most common way to write a loop, and without a doubt the first way people learn how to do it, is like this:

for (var i=0; i<items.length; i++) {
    // Magic
}

The downside of that approach, however, is that for each iteration in the loop, it needs to test the current item and check the length of array/collection you’re looping through. This is a given performance hit.

Loop 2

Moving on to an approach which has become where popular amongst well-known JavaScript developers, probably for its short and nice syntax:

for (var i=0; divs[i]; i++) {
    // Magic
}

Problem with this, though, is that for each iteration you need to do a look-up of the array to see if an object exists at the current index.

Loop 3

The way I use, is to check the length of the array/collection when the loop is instantiated, and then just compare the current iteration index to the length saved in a variable.

for (var i=0, il=divs.length; i<il; i++) {
    // Magic
}

Running a speed test

I’ve created a little JavaScript loop speed test to show the different results for each loop type and web browser. The test creates 10 000 div elements when the page is loaded, and then runs the test when you click the “Start test” button.

The results are as follows:

Web browser Loop 1 Loop 2 Loop 3
IE 6 1141 109 0
IE 7 1032 31 0
Firefox 2.0.0.13 45 149 1
Safari 3.1 2 12 1
Opera 9.27 9 10 4

I think these results really show that it is important to think about how you write your loops. Sure, 10 000 elements doesn’t match most real scenarios, but still, with richer and richer pages, lots of queries run with a number of loops, it will add up.

What’s interesting to note here is that my recommended approach, loop 3, is considerably faster in all web browsers. And it’s even more fascinating to see that the current popular approach, loop 2, is the slowest in all web browsers but Internet Explorer.

Therefore, I’d like to recommend you to look over your loops, and consider loop 3 as your new way to code loops in JavaScript.

Posted in Developing,JavaScript,Technology,Web browsers |

92 Comments

  • Very interesting. Do you define 'il' as a global variable in loop 3 intentionally for higher performance or does it work with declaring it as a local variable as well?

  • Hi Robert, this is from 2006 :)

  • Robert Nyman says:

    Felix,

    <code>il</code> is defined as a local variable as well there. Any variable name, following a comma after a <code>var</code> statement, is local as well.

    Andrea,

    Thanks for another page, with more alternatives. But apparently most people don't seem to take notice, so I hope this post helps to change that as well :-)

  • Joachim says:

    Robert, I don't exactly agree with the loop 2 test result.

    Did you try it more than once ?

    On Firefox 2.0.0.13 / Ubuntu 7.10, I got a different results the second time I launched the test.

    1st tryout, just after page load :

    loop 1 : 86

    loop 2 : 330

    loop 3 : 279

    2nd tryout, just after the first one

    loop 1 : 84

    loop 2 : 35

    loop 3 : 1

    I retried many times, and it appears I was lucky at first. Sometimes loop 2 gives ~160, sometimes it gives ~35. It seems Spidermonkey is caching some vars.

    Anyway, you're right because loop 3 is always the best, and loop 2 is a false "neat trick" since its results are not stable.

    Lesson for us: always test it in real life before optimizing !

    Question : Have you an explanation for the loop 2 result variation ?

  • Robert Nyman says:

    Joachim,

    In Firefox, I get the same, very shifting, results as you are; not in any other web browser. I have no idea why that is, although I would sort of state that the test is valid, since it seems consistently slow the first time is run, and most loops are run just once.

    And in regard to always testing in real life, I'm with you all the way! :-)

  • Jaap says:

    What I like to do when looping through collections when I know itteration order is irrelevant is the following:

    <code>

    var divs = document.getElementsByTagName("div");

    for (var i = divs.length; i–; /* nothing here */) {

      // Magic

    }

    </code>

  • I read somewhere that putting the ++ in front of the i is gonna be even better, I have no arguments or proof to back this up it's just something I read.

    What's you take on this?

    I think it might have been Crockford or maybe the Prototype.js api-doc.

  • Neovov says:

    Hi Robert,

    Great to see a bench, these tests are too few on the Internet.

    I have a couple of questions:

    – When creating the 10 000 divs you made: for (var i=0, elm; i<10000; i++)</strong>, but why do you initialize elm in the loop block? (my question is not so interesting, I was just wondering why…)

    – For each loop you don't do anything, maybe making something would be more accurate?

    – Maybe making all the loops separately would make other results?

    – And last : for (var i=0, il=divs.length; i<il; i++)</strong> I just don't understand why we can't put a var behind il for the initialization (I hope you'll answer me on that point :D)

    I found the last result a little weird, 0ms for looping 10 000 divs ? I just can't imagine how it's possible.

    PS : For loop N°2 I have these results on Firefox 2.0.0.13: 171 – 172 – 15 – 31 – 15 – 31 and so on… Is there any kind of cache?

  • Neovov says:

    @Mats : i++ and ++i aren't the same.

    i++ is the post increment while ++i is the preincrement.

  • Robert Nyman says:

    Jaap,

    Absolutely, that's an alternative too.

    Mats,

    Mats,

    As Neovov said, they do differnet things. Using ++ before, <code>i</code> would have to be 1 less for it to work.

    Neovov,

    Thanks!

    I want <code>elm</code> to be a local variable, therefore it's created within the loop (as opposed to using one extra row before the loop). The same goes for <code>il</code>; I want to declare a local variable within the scope of the function.

    I was thinking of doing something within the loops, but then I'd add the risk of any discrepancy there. Changing that as well as running the loops separately might give a little bit different results.

    This is just a very basic test to show the difference, and is meant as a basis for people to test other things with it.

  • Gerben says:

    you say that loop 2 has the downside of having to do a look-up of the array, but this is what you have to do inside the loop anyway (otherwise the loop would be useless). Therefore I would suggest a slight variation of loop 2

    <code>for (var i=0, elm; elm=divs[i]; i++) {

    // Magic (using elm)

    }</code>

    Compared to loop 3 (with a look-up added to the all loops) it's a tiny bit faster in IE, and a bit slower in FX. It is however faster than loop 2.

  • Neovov says:

    I want elm to be a local variable, therefore it’s created within the loop

    Yes, I'm right, but is there a difference between:

    <code>for (var i=0, elm; i<10000; i++) {

    elm = document.createElement("div");

    }</code>

    and

    <code>for (var i=0; i<10000; i++) {

    var elm = document.createElement("div");

    }</code>

    Because in each loop elm is declared locally

    <abbr title="By the way">BTW</abbr>: It's Neovov, not Neonov (don't worry, everybody make the mistake :D, I should write my real name instead!)

  • Gerben says:

    I just had a question Robert. In your code you are define <code>i</code> as a variable in every loop. But in loop 2 and 3 <code>i</code> has already been define as being a variable. Is there any downside to redefining something as a variable?

    As far as I can tell browsers just 'ignore' double <code>var</code> statements, not even setting it to <code>undefined</code>.

  • Robert Nyman says:

    Gerben,

    Absolutely, it's a good point. If you set the variable within the term in the loop statement and compare it with actual content to work with, the performance difference is not as big at all.

    Is there any downside to redefining something as a variable?

    Well, in this example there's really no need. Maybe I should have had different variable names to be clearer, but I don't think redefining a variable from creating a new differs that much.

    Neovov,

    Sorry about the spelling error, it's completely my bad.

    The difference with your example is that you need to create one variable for each iteration in the loop, which should affect performance more than just creating it once. Creating variables within a loop is usually seen as bad practice.

  • Chris says:

    Thanks, that was interesting. As so many of your posts :-)

  • <code>

    var i = 0, item;

    while( item = items[i++] ) {

    // Magic

    }

    </code>

    All assignments in javascript can be evaluated as a boolean.

    A few years ago, I did similar benchmarks on different methods of looping in javascript across browsers. This was the fastest that was: inorder and easy to read.

    I suspect that the reason for this method being fast, is that you're not actually comparing anything, you're just evaluating a boolean.

    If you do a search on Google for "javascript loop unrolling", or "javascript duff's device" you'll come across many interesting articles … such as http://www.websiteoptimization.com/speed/10/10-3….

    But, loop unrolling / duff's device, is complex and not easy to understand and hard(er) to test.

    I enjoy the while method, as it's so easy to read, which makes sharing my code a whole lot easier.

  • Wow … things certainly change over time in the browser market … at least for most browsers ;-)

    I just added the while method to Roberts test, and it performs similar to method two … I would have thought it would be faster.

    It still shines compared to method 1 (at least cross-browser), but method 3 beats it hands down.

    Yet another day, where I am happy that I subscribe to Roberts feed.

  • Robert Nyman says:

    Morgan,

    Ha! :-)

    To be honest, I thought that it would be as fast as fast as loop 3. We've learned something today. :-)

  • I wonder how the latest Gecko and WebKit nightlies do in comparison?

  • [...] Nyman has an interesting conversation running about JavaScript loop performance. Basically, as he points out, its far more efficient to create a variable and test on that in your [...]

  • Interesting post, Robert, thanks. I too use the method Gerben describes.

    I like these little performance nuggets o' wisdom because there so easy to implement in your scripts.

    Method 3 is probably the one to go for in the future.

  • Steven Clark says:

    Interesting take on looping Robert… not so much in JS but in other programming I have to do I generally do a similar thing.

    var myvariable = gimme_the_stuff_function;

    for(var i = 0; i < myvariable; i++)

    Which is what you're getting at I expect. Its pretty much how I was taught to program loops in an Algorithms unit in software engineering. But before that I was a happy puppy with method number 1 and I can see why a lot of people are quite happy with it.

    In another uni unit called Software Design I wrote a Java application which used method 1 (the year before) and it was a pig. The code looked correct but it was so intensive on the system it took about 2 minutes to load the main screen on a rather trivial application. So, while it mightn't impact on more trivial tasks themselves, the inefficiency of looping quickly becomes a show stopper. As does having too many nested loops, for example, and blowing Big 0 that way…

    which is what we're talking about really… Big 0 notation and measuring efficiency…

    sorry for the ramble, I'm probably a bit out of my league here :)

  • Remy Sharp says:

    I'm sure this has been discussed already, but here's what I do where the order isn't important:

    <code>

    var i = divs.length;

    while (i–) {

    // do stuff

    }

    </code>

    It's generally faster than a for loop.

    What I've never been bothered to test is whether running <code>divs = div.reverse()</code> before hand would detract from the performance benefit of doing a while loop.

  • [...] JavaScript loop performance – Robert?s talk – Web development and Internet trends – [...]

  • Robert Nyman says:

    Filemaker,

    Not sure, but my guess is that the performance in those would be about the same time (or rather, at least the difference between methods).

    Harmen,

    Yes, as Gerben states, when working with content in the loop you should get about the same performance. Something to note, though, is that that approach doesn't pass JSLint validation, which, to me at least, is a very good to tool to ensure one's scripts are good.

    Steven,

    I definitely think your in the league (or something :-) ). But yes, it's all about notation and avoiding repeated references to something which has to do a lookup/operation to return a value.

    Remy,

    Yep, that's a good one too. And I've never really bothered with the <code>reverse</code> method either.

  • Morgan,

    You're while loop only works under the assumption that <code>items</code> doesn't include any value that is <code>0</code>, <code>null</code>, <code>false</code> or <code>undefined</code>.

    This example will only log the value <code>1</code>:

    <code>var items = [1, 0];

    var i = 0, item;

    while (item = items[i++]) {

        console.log(item);

    }</code>

  • Robert Nyman says:

    Per,

    Ah, good catch.

  • [...] JavaScript loop performance – Robert’s talk.  Very interesting comparison for those of you out there writing Javascript.  (And honestly, we’ve got a number of instances where we need to iterate over 3000+ rows, so this could definitely be useful…) [...]

  • [...] JavaScript loop performance – Robert’s talk – Web development and Internet trends JavaScript loop performance (tags: ajax javascript performance) [...]

  • [...] Nyman, the original author of the perfect little JS library, DOMAssistant, has done a little loop speed test and has come to a very useful conclusion that saves a lot of processing time. Next time you do a [...]

  • Fredrik says:

    Have you tried profiling the prefix ++ notation?

    i.e: <code>for (var i = 0; i < len; ++i)</code>

    in theory it should be slightly faster since it only does exactly what you want, incrementing the var, Not incrementing and then returning the previous value..

  • liorean says:

    Robert: There's at least one other loop construct I would recommend:<code> while(elm=coll.item(i++))</code>In this syntax you use the <code>elm</code> variable inside the loop body instead of using <code>divs[i]</code> as your last example would require. (You can of course consider this a variation of second loop, which I'd write as:<code> for(i=0;elm=divs.item(i++);&#x29</code>Why do I use <code>.item</code>? IIRC there are cases where <code>coll[i]</code> throws an exception but <code>coll.item(i)</code> instead returns <code>null</code>. It's browser dependent though – some browsers actually return <code>null</code> for the hash access too.Also, I'd want to see you do those timings with an explicit lookup in each of the loop bodies, because in real live code you're not going to loop through these collections without actually using the elements for anything, and basing your timing of each example where you're actually not doing the most expensive part of the loop invariant which is always there in real world situations scews the results.

  • liorean says:

    Oh, and your post preview doesn't quite match the real posted comment, I see…

  • Robert Nyman says:

    Fredrik, liorean,

    Those are two interesting approaches. I haven't tried them out yet, but in theory they look interesting! :-)

    When it comes to timers and actually doing something within the loop, I'm well aware that it would change the results, but at the same time, then the timers can be thrown off by some irregularity in what's done within them.

    So, please see my tests as a base for doing more and more extensive tests.

  • Ricardo says:

    Hi,

    In an experiment I'm working on I'm generating 2400 divs and setting it's class with a loop. There is negligible difference between these 3 techniques you showed, loop 2 lags around 100ms behind the others (total time 1.2s). I usually set a global var for length if it's used across many functions and the array won't change.

    The thing is, using a while loop instead of for, the total time comes down to 0.8s. Also tried loop unrolling/duff's device with no effect, so I'm staying with while for now :]

  • Robert Nyman says:

    Ricardo,

    Interesting! Thanks for sharing.

  • I wrote a strinkingly similar post about different loops and their impace on performance and ease-of-coding last April, but found that benchmarks done this way are pretty useless.

    I got a lot of comments though, and there was some really good information in there.

  • Robert Nyman says:

    Christian,

    Thanks for the tip! I haven’t read that post of yours, actually, but it was very very similar. :-)

    The benchmarking is extremely basic, so I agree that this should just be a base for more extensive testing to be done.

  • Luc says:

    Here are some additional results for you. The Array.forEach is build into .NET javascript. My timings are over 2,000 elements and I am doing the following statement in each for loop:

    div.innerHTML = 'A';

    1) Loop: for (var i=0; i<divs.length; i++)

    437

    2) for (var i=0; divs[i]; i++)

    407

    3) for (var i=0, il=divs.length; i<il; i++)

    406

    4) for (var div in divs)

    422

    5) Array.forEach(divs, function)

    422

    SO THE WINNER IS (3) which is roberts pick. It would use slightly more more memory though (barely).

  • Morris says:

    Robert, Noevov, Gerben: how variable declarations work in Javascript is commonly misunderstood — the following do not do what you might expect:

    <code>

    function test1() {

    for (var i=1; i<2; i++) {

    }

    alert('test 1: i=' + String(i));

    }

    function test2() {

    for (i=1; i<2; i++) {

    }

    j=10;

    alert('test 2: i=' + String(i) + ' window.i=' + String(window.i) + ' window.j=' + String(window.j));

    var i;

    }

    test1();

    test2();

    </code>

    The rule is that a var declaration anywhere in a function applies everywhere within a function. This means:

    Making the var declaration in the for loop doesn't mean the variable is scoped to that loop – it is scoped to the function (as per test1 – which alerts i=2).

    A local variable can be declared after it is actually used (as per test2 – which also alerts i=2).

  • Greg says:

    I notice that you're looping through an HTML collection, i.e. the result of getElementsByTagName(). My understanding is that this is not a true native JavaScript array. I wonder if the results would be different if you transferred the contents of the HTML collection into a native array prior to doing the benchmarks.

  • Greg says:

    Another observation, loop 2 will fail on sparse arrays.

  • Steve says:

    Hi,

    I wondered wether it has to do with the way that collections are implemented in different version of javascript. The dom method getElementsByTagName returns an array in firefox etc. but in IE it returns a linked list. When you are setting up your loop as

    index=0; index < divs.length; index++

    ie needs to loop through the whole list to calculate the length for each iteration giving you O(n2). Please could someone confirm this for me.

    My other question is that if this is in fact true, when you index the div in the 'array' as divs[index] does ie need to loop through the linked list to find the correct position giving you O(n2) again? perhaps its better to get the parent element and then loop through the child nodes using while (currentNode.nextSibling) {

    //do stuff

    currentNode = currentNode.nextSibling; }

    Any info would be greatly appreciated because I've having some trouble with this for a while

  • Robert Nyman says:

    Luc,

    Thanks!

    Morris,

    I know that variable declarations goes for the entire function and not just the loop itself. But I can't see how this would matter here?

    Greg,

    Well, they might be, but my guess is that the results would be about the same.

    Steve,

    Actually, it returns a HTML collection in all web browsers (like a light-version of an array). So, I'm not sure IE works the way you describe it, meaning that it would probably not be necessary to loop through the <code>childNode</code>s. In my experiences, at least with IE, getting <code>childNode</code>s has been fairly much slower than, for instance, <code>getElementsByTagName</code>.

    However, I can't give you a definitive answer; I guess it all comes down to testing, testing, testing.

  • Steve says:

    Wow, thanks for the speedy reply.

    I stuck with doing the nextSibling approach in ie and 3rd loop in everything else. The loop 3 seemed to work fine in ie as well. My problem was accessing other DOM elements in each iteration – just had to cache these and it was all good. Although its off the topic of the post, there was never a problem in anything other than ie even before caching (execution < 2 secs) while ie was taking more than 30 secs for the same function. I guess the optimization of the other compilers is just better

  • Robert Nyman says:

    Steve,

    Yep, IE is so far behind their competitors, in any way imaginable…

  • Interesting.

    I am not fan of micro-benchmarks, even less those testing empty loops! You don't know if the compiler (or interpreter) detects them and optimize them.

    So I ran a little variation of your code, just putting <code>divs[i] = something</code> with something changing between each loop (<code>"Jeh" + i</code> and variants).

    Tested on FF3, IE6 and Opera 9.26. It greatly reduces the influence of the loop method, which is logical, but still shows a trend. Actually, it corroborates your finding: <code>divs.length</code> is still the slowest method! And pre-assigning the length is still the fastest. Note that the for with divs[i] can be optimized as: <code>for (var i=0, d; d=div[i]; i++)</code>, using d instead of divs[i] in the loop, so the test have an interesting side-effect, and a light speed gain (only one loop up).

    Personally, I am not fan of "assign-as-test" but it leads here to results close of your loop3. And unsurprisingly, it is near of the equivalent while loop.

    But it is dangerous: as pointed out, if the content of the array can be interpreted as false, it stops the loop! You can still do an explicit <code>(d=div[i])!=null</code> without time penalty.

    So, I will stick with an explicit comparison with a pre-assigned length variable.

    Note: in the increment part of the for loop, i++ and ++i has no importance, you can even write i += 1 if you wish (probably slower), the interpreter will just look at (and use) the resulting i.

  • Robert Nyman says:

    Philippe,

    Thanks for you input!

  • Jhuni says:

    I think you should also consider another option:

    Array.prototype.forEach(function(element){ });

    It now has a core implementation in Firefox https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference:Objects:Array:forEach that is faster then the other ones and in case you are not using firefox there is still an implementation which makes it easier to write loop 3.

    for (var i=0, il=divs.length; i<il; i++) {}

    That is very hard to read and

    var j = divs.length;
    for( var i = 0; i < j; i++ ) {}

    The above tends to have an excess of variables that can get confusing in large programs, so please consider Array.prototype.forEach. Lastly in terms of the second one if the browsers are implemented optimally that should in theory be the best way of doing it.

    for (var i=0; divs[i]; i++) { }

    The reason is that length itself in a low level implementation is just going through the pointer until it reaches null so in that respect you save time as calculating length is done with the rest of the loop. Here is some low level pointer arithmetic that is used for length in the c standard library:

    const char *eos = s;
    while (*eos++);
    return (int) (eos – s – 1);

  • Robert Nyman says:

    Jhuni,

    Thanks for your comment!

    While I don't necessarily agree about readability, you have some thought-worthy points.

  • [...] ?????????????????????????????????JavaScript??????????? JavaScript loop performance [...]

  • Niels Steenbeek says:

    Maybe I may suggest loop 4

    It loops from end to start, but is the quickest one

    for(var i = divs.length – 1; i >= 0; –i){

    // Magic

    }

  • [...] Co? podobnego, tylko ?e dla JavaScript — fajna lektura, chocia? problem, dla którego autor bada? wydajno?? nie jest zbyt ciekawy/wa?ny. Comment Comments No comments for this post [...]

  • Suresh says:

    Thanks So much. I was confused why my page took 75 seconds in IE and 5 seconds in Firefox. Now i fixed the issue. Thanks a ton.

    Thanks

    Baba

  • Robert Nyman says:

    Niels,

    Absolutely, that can be a good option.

    Suresh,

    Glad to hear that it helped!

  • Robert Nyman says:

    Tim,

    Generally, looping backwards is very fast, but not always suitable in all scenarios.

  • Tim says:

    How would:

    <code>for(var i=array.length-1;i>=0;i–) {

    // Magic

    }</code>

    compare to loop 3?

  • Charles says:

    What about:

    for (var i in items) {

    // Do something.

    }

  • Robert Nyman says:

    Charles,

    I have no concrete example here, but from what I know it's not faster. Another thing to generally think about with <code>for (var i in)</code> loops is that it goes through all data types and members in that collection, often resulting in unexpected behavior and/or values.

    Therefore, you would need to add a check to each iteration (for instance, to make sure it's really a string you're trying to manipulate), and that would definitely hurt the performance.

  • Richard says:

    After reviewing everyone's post and testing out the methods. I have come to the conclusion that the best way to do it is through example 3 that Robert posted or reversing it to check zero and count down. You can also do a while or do while loop but the speed difference between them are neglible and for loops are easier to read usually.

    I personally have decided to switch to using example three except reversed and counting down to zero. I am not sure if there is any speed difference, but if there is then I need to boost as much performance as I can out of the loop for my application of it.

  • Deepak says:

    One of my javascript code is running very slow, maybe somebody can help me with it.

    The Code is

    ***************************************

    temp = (totalexists==1)? bookinggridcols+1 : bookinggridcols-1;

    for (i=0;i<=temp;i++)

    document.write("" + bookinggridvalues[i] + "");

    ****************************************

    This spits out a huge table of 3,654 rows with each row containing 35 cells.

    I find that the above code, initially starts spitting out each row in 0.015 secs but as the file starts to grow, eventually it takes 1.5 secs for each row (after it has done around 1000 rows), and magically the last 600 odd rows becomes faster at around less 0.2 secs for each row.

    The time I have quoted is for actually printing each row, and there is no calculation involved as the values are stored in an array. The array size is always maintained at 35 in this example, but is free to grow if required. After each for loop, there is other code which populates the array, and that time is not included in the above times I have mentioned.

    Any help in this regard will be hugely appreciated.

  • Deepak says:

    Sorry forgot to add one more thing in the above post.

    I have used all the different types of looping suggested by Robert, but the results have not changed.

  • Robert Nyman says:

    Deepak,

    I'm sure the problem lies in document.write, where it for each instance has to write to the document. Try adding the values to a variable, and then, after the loop, write to the document (and rather by using .innerHTML on the element where you want to insert content).

    Also, that many lines with such a huge number is destined to become slow in a web browser.

    Good luck!

  • Deepak says:

    Thanks for the reply

    This is a report which pops out in the preview mode. So, in this case how do I write using .innherHTML.

    Also, I'm storing all the values in the array, so without the for loop am not sure how to put them to the report.

    Any pointers would be really appreciated

    Deepak

  • Robert Nyman says:

    Deepak,

    It's just a matter of having a variable and appending the string content for each loop iteration. You need to reference the element with document.getElementById("element-id").innerHTML = yourStringVariableWithHTML

  • Deepak says:

    I tried using the document.getElementById by assigning one ID for many elements.

    When I run the below line

    document.getElementById('trial').innerHTML = '';

    only the first occurance is replaced, but the subsequent occurances are not replaced. Any pointers on this is highly appreciated

  • Robert Nyman says:

    Deepak,

    IDs are unique, i.e. only one element can have the same ID. Try to approach it some other way then.

  • Deepak says:

    Any ideas on the alternate way.

    I tried with TagNames, but not working as expected

  • Robert Nyman says:

    Deepak,

    Tag names or possibly class names.

  • Erik says:

    Hello Robert,

    thanks to your post and the answers on this blog, I was able to fix some performance problems I had with JavaScript. Unfortunately I am forced to use IE as webbrowser within an application (and therefore I have to expect also IE6 or worse).

    Calculating the array lenght once instead of n times AND declaring some variables within the array declaration did the trick!

    Thanks again,

    Erik

  • Robert Nyman says:

    Erik,

    Good to hear!

  • Paolo says:

    Hi all,

    I have a problem with this loop

    for(var i=0; i =0; i–) {

    document.getElementById(aAux[i]).checked = checked;

    }

    But the result is the same.

    Do you help me, please?

    Thank's

    Paolo

  • Paolo says:

    Hi all,

    I have a problem with this loop

    <code>

    for(var i=0; i < len; i++){

    document.getElementById(aAux[i]).checked = checked;

    }

    </code>

    where sAux is a string in this format

    000_4_2390&000_4_2470&000_4_6930&004_4_9300&004_4_9370&004_4_9377& etc….

    (The number of character is 10,000…)

    I use this code before the loop for

    <code>

    var aAux = sAux.split('#');

    var iCount = aAux[1];

    aAux = aAux[0].split('&');

    var len = aAux.length;

    </code>

    And the problem is that in FF the performance is 10 seconds, while in IE 8 minutes.

    I try to apply your solution

    <code>

    for(var i=len-1; i>=0; i–) {

    document.getElementById(aAux[i]).checked = checked;

    }

    </code>

    But the result is the same.

    Do you help me, please?

    Thank's

    Paolo

  • Robert Nyman says:

    Paolo,

    Sorry, I don't really have a good suggestion…

  • For anyone stumbling across this now rather old post, you may want to have a look at the Underscore.js library's each function. It defaults to the native JS1.6 Array.forEach function if available, and otherwise uses the same technique 3 as above:

    <code>

    var each = _.forEach = function(obj, iterator, context) {

    try {

    if (nativeForEach && obj.forEach === nativeForEach) {

    obj.forEach(iterator, context);

    } else if (_.isNumber(obj.length)) {

    for (var i = 0, l = obj.length; i < l; i++) iterator.call(context, obj[i], i, obj);

    } else {

    for (var key in obj) {

    if (hasOwnProperty.call(obj, key)) iterator.call(context, obj[key], key, obj);

    }

    }

    } catch(e) {

    if (e != breaker) throw e;

    }

    return obj;

    };

    </code>

  • Robert Nyman says:

    Oskar,

    Cool, thanks for the input!

  • [...] JavaScript loop performance – Robert’s talk [...]

  • [...] ?????????????????????????????????JavaScript??????????? JavaScript loop performance [...]

  • Joe says:

    PRE vs. POST increment:
    ++i; is always faster than i++, because it requires TWO less REGISTER instruction for the processor.

    I forget the exact assembly commands, but basically:

    i++ tells the processor to ‘ (a) PUSH the value to a separate register location… (b) INCREMENT the value, and then (c) PUSH it back to it’s original register location.’ …(then access the final value at the original memory location)

    ++i tells the processor to ‘(a) INCREMENT the value’ …(then access the value , still at the original memory location)

    so you see the two PUSH instructions are eliminated… and anytime you can eliminate both processor instructions AND moving memory around execution is faster…

    good compilers tend to catch this i++ misuse and optimize it as ++i… however, i recall i ran a javascript test on this and saw a fair difference between i++ and the faster ++i.

    -jsfunfun

  • Robert Nyman says:

    Joe,

    Thanks for the input!

  • [...] Robert Nyman has a good post about the fastest way to code for…in loops, which is: [...]

  • [...] JavaScript loop performance. Opis wydajno?ci p?tli w [...]

  • Clint says:

    I believe the reason you’re seeing a big performance gain in this case is because you’re looping over an HTMLCollection (i.e., the collection of div nodes). Each time you ask for the length of an HTMLCollection, the DOM nodes have to be re-counted (since the DOM may have changed), hence the benefit of caching the length. This isn’t the case with a regular array, however, and your #3 approach probably wouldn’t be as beneficial.

  • Robert Nyman says:

    Clint,

    Perhaps, but it seems to generally give better results.

  • TVD says:

    @Robert: Really solid article! We used #3 to improve the for loop in Version 1.1.0 of Entourage.js Google Analytics Extension:
    http://techoctave.com/c7/posts/58-entourage-js-automatic-download-tracking-for-asynchronous-google-analytics

    var links = document.links;

    for (var i=0, l=links.length; i < l; i++) {
    links[i].onclick = autograph;
    }

    Caching number of links was a really good idea and increased performance.

  • [...] looping through arrays, use a fast method for iterating over the elements in the array, [...]

  • […] as tested here (http://www.robertnyman.com/2008/04/11/javascript-loop-performance/), it should probably be written so that the length is only calculated […]

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>