295

I've heard this quite a few times. Are JavaScript loops really faster when counting backward? If so, why? I've seen a few test suite examples showing that reversed loops are quicker, but I can't find any explanation as to why!

I'm assuming it's because the loop no longer has to evaluate a property each time it checks to see if it's finished and it just checks against the final numeric value.

I.e.

for (var i = count - 1; i >= 0; i--)
{
  // count is only evaluated once and then the comparison is always on 0.
}
dreamcrash
  • 47,137
  • 25
  • 94
  • 117
djdd87
  • 67,346
  • 27
  • 156
  • 195
  • 6
    hehe. that will take indefinetely. try i-- – StampedeXV Aug 27 '09 at 11:54
  • ok. not indefinetely. Another thing: did you test the assumption? Like say, set count to 1000000 and let it run upwards once and once downwards? – StampedeXV Aug 27 '09 at 11:56
  • 6
    Backwards `for` loop is faster because the upper-bound (hehe, lower-bound) loop control variable does not have to be defined or fetched from an object; it is a constant zero. – Josh Stodola Aug 27 '09 at 18:52
  • 3
    Have you tried a fiddler or any performance tool for javascript? – radu florescu Oct 30 '12 at 10:11
  • @Floradu88: Really, not yet but I believe this is correct. I saw that in several articles and editor suggestions :) – Afshin Mehrabani Oct 30 '12 at 10:13
  • 92
    There is [no real difference](http://jsperf.com/increment-vs-decrement-2/2). Native loop constructs are always going to be *very fast*. Don't worry about their performance. – James Allardice Oct 30 '12 at 10:13
  • @billyonecan: Lol! 58% slower to increment here. Wtf. – Lightness Races in Orbit Oct 30 '12 at 10:17
  • 25
    @Afshin: For questions like this, please _show us_ the articles you're referring to. – Lightness Races in Orbit Oct 30 '12 at 10:18
  • @billyonecan if you convert the comment into answer you have my vote up – radu florescu Oct 30 '12 at 10:32
  • 5
    related: [Is it faster to count down than it is to count up?](http://stackoverflow.com/questions/2823043/is-it-faster-to-count-down-than-it-is-to-count-up) – Paolo Moretti Oct 30 '12 at 10:32
  • @billyonecan that test you posted is more so JS Array test than -- vs ++ – Ashwin Prabhu Oct 30 '12 at 10:55
  • @AshwinPrabhu yup I saw [your revision](http://jsperf.com/increment-decrement-looping/6) – billyonecan Oct 30 '12 at 11:01
  • 23
    There is difference mainly important for very low-end and battery powered devices. The differences is that with i-- you compare to 0 for the end of the loop, while with i++ you compare with number > 0. I believe the performance difference was something like 20 nanoseconds (something like cmp ax,0 vs. cmp ax,bx) - which is nothing but if you loop thousands of times per second, why not have 20 nanoseconds gain for each :) – luben Oct 30 '12 at 16:03
  • 1
    You are not really asking the right question based on the code samples you show. It is not a case of i-- being fast, it is the loop construct where the array length is only evaluated once that is the speed up. – Steve Oct 30 '12 at 16:53
  • So how does `for(i = 0; i < arr.length; i++)` compare with `for(i in arr)`? – fluffy Oct 30 '12 at 20:11
  • 3
    Downvoting because there are no benchmarks, just an incorrect hypothetical. – Mikhail Oct 30 '12 at 22:12
  • 1
    @Lyuben: Completely wrong. Something like comparing two registers and comparing a register against zero are going to run at the same rate. – Billy ONeal Oct 31 '12 at 02:22
  • @Billy ONeal: How is it so, when in one case the CPU has to fetch the value of the register and in the other it does not fetch anything? – luben Oct 31 '12 at 08:47
  • @BillyONeal comparing two registers means both of them should be set, but comparing with 0 needs one register. But since the difference is almost nothing and it is just in initialization of loop, I think using up count in many cases is more sufficient as it increases readability. – Saber Oct 31 '12 at 10:41
  • 1
    I remember programming assembly on the 6502 processor. The decrement version _was_ faster back then. But that's ages ago... Shouldn't really make any (measurable) difference today. – Axel Oct 31 '12 at 13:54
  • @BillyONeal: It all depends on the processor. In case of the decrement, there might be cases when the comparison with zero isn't even necessary. – Axel Oct 31 '12 at 13:57
  • 2
    @Axel: Completely irrelevant. In C, you might have a point. In JavaScript? None -- there's nowhere near that much of a 1:1 relationship between code and hardware in that language. (For instance, JavaScript doesn't have integers, so this is always going to be a floating point comparison in any case) – Billy ONeal Oct 31 '12 at 17:26
  • 1
    @JamesAllardice The benchmarks show the decrement version being consistently faster than the rest, across all browsers. – NullUserException Oct 31 '12 at 17:46
  • @NullUserException - My point was that while benchmarks may show that, the difference in real terms is insignificant and not worth worrying about. It's about as micro as micro-optimisations can get really. Also note that the benchmark I linked to falls into the trap mentioned in the highest voted answer here. – James Allardice Oct 31 '12 at 17:51
  • @JamesAllardice - it's never insignificant if you write real-time game or make real-time rendering. Imagine for a moment that you have 200 objects that you have to loop through every frame and that you have 50 frames/per seconds - then the loop will be executed 1000 times per second. Every gain seems good to me in this case. – luben Nov 01 '12 at 05:36
  • @BillyONeal: Yes, and Javascript didn't even exist back then. But I referred to your comment "Something like comparing two registers and comparing a register against zero are going to run at the same rate.", which is not true for all processors. – Axel Nov 01 '12 at 08:27
  • 1
    What so many answers are missing, even the accepted one with 700 votes as of Sept 2015, is that you can assign *multiple* variables in the first part of your for loop. In the following way for example you only access the length of the array once: `for (var i=0, n=msSeriesNames.validIds.length; i – Dexygen Sep 03 '15 at 14:53

34 Answers34

945

It's not that i-- is faster than i++. Actually, they're both equally fast.

What takes time in ascending loops is evaluating, for each i, the size of your array. In this loop:

for(var i = array.length; i--;)

You evaluate .length only once, when you declare i, whereas for this loop

for(var i = 1; i <= array.length; i++)

you evaluate .length each time you increment i, when you check if i <= array.length.

In most cases you shouldn't even worry about this kind of optimization.

Joel Christophel
  • 2,604
  • 4
  • 30
  • 49
alestanis
  • 21,519
  • 4
  • 48
  • 67
  • 32
    is it worth to introduce a variable for array.length and use it in the for loop's head? – ragklaat Oct 30 '12 at 10:13
  • 45
    @ragatskynet: No, unless you are setting up a benchmark and want to make a point. – Jon Oct 30 '12 at 10:14
  • 2
    I think this may be misleading... i-- is still evaluated and compared to 0 every cycle. Are you saying it's more efficient to compare i to 0 than to length? This sounds dubious to me. – Yevgeny Simkin Oct 30 '12 at 10:14
  • 34
    @ragatskynet It depends: will it be faster to evaluate `.length` a certain number of times or to declare and define a new variable? In most cases, this is premature (and wrong) optimization, unless your `length` is very expensive to evaluate. – alestanis Oct 30 '12 at 10:15
  • 4
    @Dr.Dredel no, i'm not saying that one evaluation is faster than the other. What i'm saying is that to be able to compare `i` to `.length` you have to *get* the array's length, and that's what takes more time. – alestanis Oct 30 '12 at 10:15
  • 13
    @Dr.Dredel: It's not the comparison - it's the evaluation. `0` is faster to evaluate than `array.length`. Well, supposedly. – Lightness Races in Orbit Oct 30 '12 at 10:16
  • 1
    right, so if you had the length in a variable then it would take the same amount of time, I believe. – Yevgeny Simkin Oct 30 '12 at 10:17
  • I never used that kind of "improvement". Though I was seeing sometimes people suggesting it. I rather not mess my code up with those (kind of) useless variables. – ragklaat Oct 30 '12 at 10:18
  • 4
    @Dr.Dredel: No, because evaluating a variable requires a lookup of some sort, whereas evaluating `0` does not because you already have its value. This is in fact exactly what we're talking about, because `array.length` is a variable. – Lightness Races in Orbit Oct 30 '12 at 10:19
  • 3
    @Dr.Dredel: Not necessarily. `array.length` requires two name lookups. One for `array` and then another one for `length`, while a variable would only require one. Of course, the difference is likely miniscule. – hammar Oct 30 '12 at 10:19
  • 1
    This case is often described in connection to live node collections. Their `length`, if not cached, is not only accessed on each iteration, but also updated as the elements are recounted in the DOM-tree. – katspaugh Oct 30 '12 at 10:35
  • 24
    What is worth mentioning is that we are talking about interpreted languages such as Ruby, Python. Compiled languages e.g. Java have optimizations on compiler level which which will "smooth" these differences to the point that it does not matter if `.length` is in declaration of `for loop` or not. – Haris Krajina Oct 30 '12 at 11:31
  • 2
    Worth pointing out though that the backwards loop here is much faster in all versions of IE than the forward version. Since old IE is by far the slowest engine, if you can be happy with backwards iteration, use it. – Chris Moschini Oct 30 '12 at 12:21
  • 4
    According to this benchmark, IE had performance gains up to 30% faster. I'd say for large datasets, this is worth it if your audience uses IE. http://www.erichynds.com/javascript/javascript-loop-performance-caching-the-length-property-of-an-array/ – Isaac Fife Oct 30 '12 at 15:25
  • 2
    It's also worth mentioning that iterating backwards through a dynamic array can be useful if you intend to remove one or more elements during the loop. – Bok McDonagh Oct 30 '12 at 16:03
  • What about `for(var i in myArray)`? – melanke Oct 30 '12 at 19:28
  • 1
    JS engine has enough brain to figure out if body of a loop doesn't modify array, so it won't need to re-check length of the array. But that depends on the implementation of JavaScript engine. Going down to 0 uses only one variable, vs 2 in all other cases which is better for optimizer or JITs. Check below for my answer. – Pavel P Oct 30 '12 at 19:40
  • 1
    The evaluation of array.length will be eliminated by a good interpreter / compiler. The topic is the 'compare with 0' - see my answer below. – H.-Dirk Schmitt Oct 31 '12 at 10:03
  • @Dolphin You are wrong in the assumption that in Java it does not matter. Not all Java programs run on fast multiprocessors or have JIT. I have lots of experience with J2ME and embedded applications and `.length` in `for` matters. You can also feel the difference between using a local and instance variable. `i--` loop was always preferred. Note that java has a special instruction to compare with zero which makes even the comparison faster. – Sulthan Oct 31 '12 at 11:25
  • I would even dare to say that for(var i = 1; i <= somelength; i++ ) is faster! – Żubrówka Oct 31 '12 at 12:27
  • 8
    I always use this: `for (var i = 0, c = array.length; i < c; i++)`. It's an easy and clear enough optimisation, in any language, so it doesn't hurt. – Constantino Tsarouhas Oct 31 '12 at 13:00
  • 2
    @H.-DirkSchmitt: That depends on the language and the specific evaluation. For example, in C, using `for (i = 0; i < strlen(s); i++)` to iterate over a list will make a substantial difference in the running time, since `strlen(s)` cannot be optimized out and runs in linear time in the length of the string. – David Robinson Oct 31 '12 at 13:43
  • @DavidRobinson you C loop if `s` is `const char * const s` the compiler should be able to tell the invariant and be able to inline. – Alexander Oh Dec 04 '12 at 22:35
  • Let us optimize it even more :-) Use `--i` instead of `i--`, because preincrement is faster than postincrement. You are going to save several nanoseconds. – mark Mar 20 '13 at 13:58
  • In most cases your array won't be big enough to make a noticeable difference, so as alestanis stated you shouldn't even worry about this kind of optimization. In cases where you must ascend through the array (e.g., items are ordered by priority), then you can do this: `for (var i=0, imax=array.length; i – thdoan Jan 15 '15 at 04:32
  • 1
    @HarisKrajina: JavaScript isn't an "interpreted language." It's a language. With modern browsers (even in 2011), it was unlikely except (in 2011) for IE that JavaScript was interpreted; instead, it's just-in-time-compiled to machine code. (Chrome's V8 even does two-stage compilation, initially compiling as fast as possible, then going back and doing aggressive optimizations in hotspots if it finds any.) – T.J. Crowder Mar 31 '15 at 12:17
  • 1
    @Sulthan: It's not just Java that is faster comparing to zero. x86 sets flags after most ALU ops, so often you don't need a separate compare instruction if counting down to zero, just `dec/jnz`. This sort of thing probably applies to some other ISAs. – Peter Cordes Aug 21 '15 at 04:27
  • It's bad form to perform an evaluation during a loop which *never changes*. `.length` should be applied to a variable *before* the loop, and the variable used in the loop. A better comparison of forward vs reverse loops would *not* evaluate length during the loop. My benchmarks, using a variable, show that (on Chrome 88.x) all reverse loops are faster than all forward loops. – johny why Feb 10 '21 at 21:41
  • i disagree with the statement "you shouldn't even worry about this". Too many coders forget that users might not have computers as powerful as the coder's computer. If a loop executes thousands of times, and if you have many such loops in your process, it will likely impact user experience or system performance. – johny why Feb 10 '21 at 21:44
208

This guy compared a lot of loops in javascript, in a lot of browsers. He also has a test suite so you can run them yourself.

In all cases (unless I missed one in my read) the fastest loop was:

var i = arr.length; //or 10
while(i--)
{
  //...
}
Baldrickk
  • 4,291
  • 1
  • 15
  • 27
Tom Ritter
  • 99,986
  • 30
  • 138
  • 174
  • Nice :) But there is no backward "for"-loop tested... But the for loops mentioned by peirix or searlea should be pretty much the same as the "while" loop with "i--" as its condition. And that was the fastest loop tested. – SvenFinke Aug 27 '09 at 12:15
  • 12
    Interesting, but I wonder if pre-decrement would be even faster. Since it won't have to store the intermediate value of i. – tvanfosson Aug 27 '09 at 12:20
  • If I remember correctly, my hardware-course prof said, that test for 0 or not 0 is fastest possible "calculation". In while(i--) the test is always a test for 0. Maybe that's why this is fastest? – StampedeXV Aug 27 '09 at 12:28
  • @StampedeXV: Yep, that's why it's considered the fastest. Interestingly, when I ran the benchmark that @Tom linked to, the reverse loop didn't come out any faster than the normal `for` loop, but that might just be because of the small amount of iterations. – Sasha Chedygov Oct 08 '10 at 18:17
  • 4
    @tvanfosson if you pre-decrement `--i` then you have to use `var current = arr[i-1];` inside the loop or it will be off by one... – DaveAlger Jul 31 '12 at 16:04
  • Doesn't work in FireFox 14.0.1. Also does not pass the jsLinter. You need a comparison operator, not an assignment. – mrbinky3000 Aug 17 '12 at 17:13
  • This isn't always the fastest iteration, e.g. http://jsperf.com/for-vs-foreach/57 – Gajus Jan 30 '13 at 00:07
  • The `!isInt` test on the benchmark page would be faster written as `i !== ~~i`. The test on the page uses a regex, which means it's converting i to a string. No wonder that test came out so slow. – Keen Apr 19 '13 at 18:59
  • 2
    I've heard that i-- can be faster than --i because in the second case the processor needs to decrement and then test against the new value (there's a data dependency between the instructions), while in the first case the processor can test the existing value and decrement the value some time later. I'm not sure if this applies to JavaScript or only very low-level C code. – marcus May 19 '13 at 00:56
  • Unfortunately Oracle seems to have restructured its blog content due to which both links in your post aren't valid anymore :( – RBT Jul 07 '17 at 02:19
  • @RBT I've edited the links. As I couldn't find the current links to the content (if it still exists) I replaced them with web archive links. The test page still works. – Baldrickk Jul 13 '17 at 14:11
  • `--i` vs `i--`: On two out of three benchmarks, `--i` is faster. On Chrome 88.x on Windows 10: jsben.ch: `--i` is faster, https://jsben.ch/RpG0K. jsbench.me: `i--` is faster, https://jsbench.me/i2kkzuk4kl/1. measurethat.net: `--i` is faster, https://measurethat.net/Benchmarks/ShowResult/162675. – johny why Feb 10 '21 at 21:52
  • var array=new Array(100000).fill(1); var ms; ms=-performance.now(); for(var i=0;i – Rick Edwards Jun 26 '23 at 19:40
  • what about: for (let i = arr.length; i > 0; --i) {}, or let i = arr.length; while(--i>-1) {} – alex Aug 31 '23 at 15:03
132

I try to give a broad picture with this answer.

The following thoughts in brackets was my belief until I have just recently tested the issue:

[[In terms of low level languages like C/C++, the code is compiled so that the processor has a special conditional jump command when a variable is zero (or non-zero).
Also, if you care about this much optimization, you could go ++i instead of i++, because ++i is a single processor command whereas i++ means j=i+1, i=j.]]

Really fast loops can be done by unrolling them:

for(i=800000;i>0;--i)
    do_it(i);

It can be way slower than

for(i=800000;i>0;i-=8)
{
    do_it(i); do_it(i-1); do_it(i-2); ... do_it(i-7);
}

but the reasons for this can be quite complicated (just to mention, there are the issues of processor command preprocessing and cache handling in the game).

In terms of high level languages, like JavaScript as you asked, you can optimize things if you rely on libraries, built-in functions for looping. Let them decide how it is best done.

Consequently, in JavaScript, I would suggest using something like

array.forEach(function(i) {
    do_it(i);
});

It is also less error-prone and browsers have a chance to optimize your code.

[REMARK: not only the browsers, but you too have a space to optimize easily, just redefine the forEach function (browser dependently) so that it uses the latest best trickery! :) @A.M.K. says in special cases it is worth rather using array.pop or array.shift. If you do that, put it behind the curtain. The utmost overkill is to add options to forEach to select the looping algorithm.]

Moreover, also for low level languages, the best practice is to use some smart library function for complex, looped operations if it is possible.

Those libraries can also put things (multi-threaded) behind your back and also specialized programmers keep them up-to-date.

I did a bit more scrutiny and it turns out that in C/C++, even for 5e9 = (50,000x100,000) operations, there is no difference between going up and down if the testing is done against a constant like @alestanis says. (JsPerf results are sometimes inconsistent but by and large say the same: you can't make a big difference.)
So --i happens to be rather a "posh" thing. It only makes you look like a better programmer. :)

On the other hand, for-unrolling in this 5e9 situation, it has brought me down from 12 sec to 2.5 sec when I went by 10s, and to 2.1 sec when I went by 20s. It was without optimization, and optimization has brought things down to unmeasureable little time. :) (Unrolling can be done in my way above or using i++, but that does not bring things ahead in JavaScript. )

All in all: keep i--/i++ and ++i/i++ differences to the job interviews, stick to array.forEach or other complex library functions when available. ;)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Barney Szabolcs
  • 11,846
  • 12
  • 66
  • 91
  • Thanks, I had the chance last year to have a glimpse on optimization techniques: we were given a loopy thing to be optimized in a competition. It was not much more complicated than this and I could not see if I could do anything sensible. Then some guys using smart libraries and for-unlooping had 10 to 20 times faster codes. I was shocked... then went ahead unlooping an image filtering function: 4x speed-up. It is surprising that you can be faster by doing actually more unit operations. – Barney Szabolcs Oct 30 '12 at 11:44
  • 18
    The key word is "can be". Your unrolled loop might also be slower than the original one. When optimizing, always measure so you know exactly what impact your changes had. – jalf Oct 30 '12 at 11:59
  • 1
    @jalf true indeed, +1. Different unlooping lenghts(>=1) are different in efficiency. That is why it is more convenient to leave this job to libraries if possible, not to mention that browsers run on different architectures so it might be better if they decide how to do `array.each(...)`. I don't think they would try and experiment with unlooping plain for-loops. – Barney Szabolcs Oct 30 '12 at 12:13
  • It's "unrolling", not "unlooping". In addition, `++i` is not any faster than `i++`- they are both one INC instruction if the result is not taken. – Puppy Oct 30 '12 at 12:54
  • @DeadMG you are absolutely right, I have tested it too, I'll skip that part from the answer, corrected unlooping to unrolling. Please check it is not confusing now. – Barney Szabolcs Oct 30 '12 at 13:35
  • 10 years of writing for and foreach loops to run through arrays... this is the first time I've seen the array.forEach() thing. I love it!! Do other languages have this? PHP? C#? Ruby? – Jordan Hudson Oct 30 '12 at 17:55
  • actually @BarnabasSzabolcs when considering large javascript array you are wrong. I [tested](http://jsperf.com/optimizing-iterating-over-imagedata-array/2) this the other day and there is a noticeable difference between a while down loop than a while up loop. also unrolling the loop (a duff machine) is way quicker - (also noticeable only in large arrays) and another thing - in Js there the slowest loop is a foreach loop - meant to be used for objects and not arrays, again a quite noticable difference. I didn't answer the question because I don't know __why__ this is the outcome – alonisser Oct 30 '12 at 17:55
  • I guess I could just google to answer my own question... http://msdn.microsoft.com/en-us/library/zecdkyw2.aspx – Jordan Hudson Oct 30 '12 at 17:59
  • This is for me really right way of seeing things: if you have libraries/functions to do what you want, use them. But asking those questions **is legitimate**! Understanding your language **is good**. Just don't do that every 5 minutes – lajarre Oct 30 '12 at 18:58
  • @alonisser I did not see for vs forEach in your performance test. But look at this thread: [for vs forEach](http://stackoverflow.com/questions/9746579/for-loop-vs-foreach-perfomance-in-javascript-and-credibility-of-jsperf-results). I think the winner there is forEach as expected. – Barney Szabolcs Oct 30 '12 at 19:19
  • "... All in all: keep i--/i++ and ++i/i++ ..." did you mean to have --i in there somewhere instead of a second i++? not trying to be nit picky, but it's an important change for what seems to be the summary of your answer – Logan Besecker Oct 31 '12 at 00:09
  • I meant to express, there is no real difference in speed in choosing i-- or i++ or ++i or --i style for looping. I have also changed the text at the end, hope it is a bit more to the point. – Barney Szabolcs Oct 31 '12 at 00:23
  • 1
    @BarnabasSzabolcs The question is for JavaScript specifically, not C or other languages. In JS there _is_ a difference, please see my answer below. Although not applicable to the question, +1 good answer! – A.M.K Oct 31 '12 at 14:17
  • @A.M.K Thanks for your answer it was really useful, mind you jsPerf tests are always special in a way, the advantages change with array size, number of other loaded objects, other stuff, browser versions etc. It is worth remaining flexible and to the point in the main code, I have updated my answer accordingly. Nevertheless it is the easiest to macro-out `forEach`es to your favorite algo when going production and minimizing the code anyway. – Barney Szabolcs Oct 31 '12 at 16:24
  • 1
    And there you go - `+1` to get you a `Great Answer` Badge. Really great answer. :) – Rohit Jain Nov 25 '12 at 13:42
  • C/C++ is not a language. C is and C++ is, but no language is called C/C++. – Sebastian Mach Nov 27 '12 at 12:10
  • 1
    APL/A++ is not a language either. People use these to express that they are not interested in language specifics, but something that those languages share. – Barney Szabolcs Nov 27 '12 at 13:49
  • @BarnabasSzabolcs: Your 2nd last paragraph about timing should really mention right away that it was with no C compiler optimization, because that makes it almost completely irrelevant. Also, a loop with no work in the body will be limited by the CPUs branch throughput. e.g. Intel Sandybridge takes 2 cycles per iteration to execute an empty loop. It's not surprising or useful that`1: dec eax/jnz 1` and `2: inc eax / cmp eax, edx / jne 2` run in the same time. What's interesting is that counting up uses one more instruction. One trick is to negate your loop counter, and count up toward 0 – Peter Cordes Aug 21 '15 at 04:36
35

i-- is as fast as i++

This code below is as fast as yours, but uses an extra variable:

var up = Things.length;
for (var i = 0; i < up; i++) {
    Things[i]
};

The recommendation is to NOT evaluate the size of the array each time. For big arrays one can see the performance degradation.

sainiuc
  • 1,697
  • 11
  • 13
  • 7
    You are plainly wrong here. Now loop control needs extra internal variable (i and up) and depending on JavaScript engine this may limit potential to optimize the code. JITs will translate simple loops to direct machine opcodes, but if loops have too many variables then JIT won't be able to optimize as good. Generally, it's limited by architecture or cpu registers that JIT uses. Initializing once and going down simply cleanest solution and that's why it's recommended all over the place. – Pavel P Oct 30 '12 at 18:28
  • The additional variable will be eliminated by the optimizer of a common interpreter/compiler. The point is the 'compare to 0' - see my answer for further explanation. – H.-Dirk Schmitt Oct 31 '12 at 11:20
  • 2
    Better to put 'up' inside the loop: `for (var i=0, up=Things.length; i – thdoan Jan 15 '15 at 04:28
  • Why internal variable could create issues? This is mistaken because the loop control won't have an "extra variable" because `up` exactly as `Things.length` is not passed by reference (as an object or array would be) but directly by value. In other words, it is inserted in the loop control exactly as the number 10 or 100000. You just renamed it OUTSIDE of the loop, so no difference whatsoever. For this reason the answer in itself is entirely valid. When seeing i < up the loop control sees i < 10 not i < (a reference to number 10). Actually `up` stores inside it a primitive, don't forget that. – Eve Nov 29 '21 at 11:16
25

Since, you are interested in the subject, take a look at Greg Reimer's weblog post about a JavaScript loop benchmark, What's the Fastest Way to Code a Loop in JavaScript?:

I built a loop benchmarking test suite for different ways of coding loops in JavaScript. There are a few of these out there already, but I didn't find any that acknowledged the difference between native arrays and HTML collections.

You can also do a performance test on a loop by opening https://blogs.oracle.com/greimer/resource/loop-test.html (does not work if JavaScript is blocked in the browser by, for example, NoScript).

EDIT:

A more recent benchmark created by Milan Adamovsky can be performed in run-time here for different browsers.

For a Testing in Firefox 17.0 on Mac OS X 10.6 I got the following loop:

Benchmark example.

dreamcrash
  • 47,137
  • 25
  • 94
  • 117
  • @dreamcash On Chrome 88.x, all reverse loops are always faster than all forward loops. https://jsben.ch/eng8b, https://www.measurethat.net/Benchmarks/ShowResult/162677, https://jsbench.me/5ykkzsysa9 . Sometimes reverse-for, sometimes reverse-optimized-for, sometimes reverse-while. – johny why Feb 10 '21 at 20:00
  • @johnywhy okey I miss-understood okey so it still makes a bit of a difference. Will you post an answer with those results? – dreamcrash Feb 10 '21 at 20:03
22

It's not the -- or ++, it is the compare operation. With -- you can use a compare with 0, while with ++ you need to compare it with the length. On the processor, compare with zero is normally available, while compare with a finite integer requires a subtraction.

a++ < length

is actually compiled as

a++
test (a-length)

So it takes longer on the processor when compiled.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Dr BDO Adams
  • 416
  • 1
  • 5
  • 13
15

I've seen the same recommendation in Sublime Text 2.

Like it was already said, the main improvement is not evaluating the array's length at each iteration in the for loop. This a well-known optimization technique and particularly efficient in JavaScript when the array is part of the HTML document (doing a for for the all the li elements).

For example,

for (var i = 0; i < document.getElementsByTagName('li').length; i++)

is much slower than

for (var i = 0, len = document.getElementsByTagName('li').length; i < len; i++)

From where I'm standing, the main improvement in the form in your question is the fact that it doesn't declare an extra variable (len in my example)

But if you ask me, the whole point is not about the i++ vs i-- optimization, but about not having to evaluate the length of the array at each iteration (you can see a benchmark test on jsperf).

BBog
  • 3,630
  • 5
  • 33
  • 64
  • 1
    I have to take exception to the word *calculating* here. See my comment on [Pavel's answer](http://stackoverflow.com/a/13145309/418413). The ECMA spec states that the array length is not calculated when you refer to it. – kojiro Oct 30 '12 at 21:31
  • Would 'evaluating' be a better choice? Interesting fact btw, I did not know that – BBog Oct 31 '12 at 07:46
  • The additional variable will be eliminated by the optimizer of a common interpreter/compiler. The same applies to the array.length evaluation. The point is the 'compare to 0' - see my answer for further explanation. – H.-Dirk Schmitt Oct 31 '12 at 11:24
  • @H.-DirkSchmitt your common-sense answer aside, for long in the history of JavaScript the compiler did *not* optimize away the performance cost of the lookup chain. AFAIK V8 was the first to try. – kojiro Oct 31 '12 at 12:39
  • @H.-DirkSchmitt just like kojiro said, this is as well-known and well-established trick. Even if it is no longer relevant in modern browsers, that still doesn't make it obsolete. Besides, doing it with either introducing a new variable for length or with the trick in OP's question, it's still the best way, imo. It's just a smart thing to do and good practice, I do not think it has anything to do with the fact that the compiler was optimized to take care of something often done in a bad way in JS – BBog Oct 31 '12 at 12:48
  • IMO one should use this style in all but the most trivial cases. Sometimes one needs to refer to the length inside the loop, then this construct comes in handy – Sebastian Nov 02 '13 at 09:08
15

I don't think that it makes sense to say that i-- is faster that i++ in JavaScript.

First of all, it totally depends on JavaScript engine implementation.

Secondly, provided that simplest constructs JIT'ed and translated to native instructions, then i++ vs i-- will totally depend on the CPU that executes it. That is, on ARMs (mobile phones) it's faster to go down to 0 since decrement and compare to zero are executed in a single instruction.

Probably, you thought that one was waster than the other because suggested way is

for(var i = array.length; i--; )

but suggested way is not because one faster then the other, but simply because if you write

for(var i = 0; i < array.length; i++)

then on every iteration array.length had to be evaluated (smarter JavaScript engine perhaps could figure out that loop won't change length of the array). Even though it looks like a simple statement, it's actually some function that gets called under the hood by the JavaScript engine.

The other reason, why i-- could be considered "faster" is because JavaScript engine needs to allocate only one internal variable to control the loop (variable to the var i). If you compared to array.length or to some other variable then there had to be more than one internal variable to control the loop, and the number of internal variables are limited asset of a JavaScript engine. The less variables are used in a loop the more chance JIT has for optimization. That's why i-- could be considered faster...

Pavel P
  • 15,789
  • 11
  • 79
  • 128
  • 3
    It's probably worth careful phrasing about how `array.length` is evaluated. The length is not *calculated* when you refer to it. (It's just [a property that gets set whenever an array index is created or changed](http://ecma-international.org/ecma-262/5.1/#sec-15.4)). When there is additional cost, it is because the JS engine has not optimized the lookup chain for that name. – kojiro Oct 30 '12 at 21:30
  • Well, not sure what Ecma spec says, but knowing about some internals of different JavaScript engines it's not simple `getLength(){return m_length; }` because there is some housekeeping involved. But if you try to think backwards: that would be quite ingenious to write array implementation where length would need to be actually calculated :) – Pavel P Oct 30 '12 at 21:37
  • the ECMA spec *requires* that the length property be already calculated. The `length` must be updated immediately whenever a property-that-is-an-array-index is added or changed. – kojiro Oct 30 '12 at 21:50
  • What I'm trying to say is that it's pretty hard to violate the spec if you try think about it. – Pavel P Oct 30 '12 at 21:56
  • 1
    x86 is like ARM in that respect. `dec/jnz` vs. `inc eax / cmp eax, edx / jne`. – Peter Cordes Aug 21 '15 at 04:44
15

Short answer

For normal code, especially in a high level language like JavaScript, there is no performance difference in i++ and i--.

The performance criteria is the use in the for loop and the compare statement.

This applies to all high level languages and is mostly independent from the use of JavaScript. The explanation is the resulting assembler code at the bottom line.

Detailed explanation

A performance difference may occur in a loop. The background is that on the assembler code level you can see that a compare with 0 is just one statement which doesn't need an additional register.

This compare is issued on every pass of the loop and may result in a measurable performance improvement.

for(var i = array.length; i--; )

will be evaluated to a pseudo code like this:

 i=array.length
 :LOOP_START
 decrement i
 if [ i = 0 ] goto :LOOP_END
 ... BODY_CODE
 :LOOP_END

Note that 0 is a literal, or in other words, a constant value.

for(var i = 0 ; i < array.length; i++ )

will be evaluated to a pseudo code like this (normal interpreter optimisation supposed):

 end=array.length
 i=0
 :LOOP_START
 if [ i < end ] goto :LOOP_END
 increment i
 ... BODY_CODE
 :LOOP_END

Note that end is a variable which needs a CPU register. This may invoke an additional register swapping in the code and needs a more expensive compare statement in the if statement.

Just my 5 cents

For a high level language, readability, which facilitates maintainability, is more important as a minor performance improvement.

Normally the classic iteration from array start to end is better.

The quicker iteration from array end to start results in the possibly unwanted reversed sequence.

Post scriptum

As asked in a comment: The difference of --i and i-- is in the evaluation of i before or after the decrementing.

The best explanation is to try it out ;-) Here is a Bash example.

 % i=10; echo "$((--i)) --> $i"
 9 --> 9
 % i=10; echo "$((i--)) --> $i"
 10 --> 9
Community
  • 1
  • 1
H.-Dirk Schmitt
  • 1,159
  • 8
  • 14
  • 1
    1+ Good explanation. Just a question a little out of scope, could you please explain the difference between `--i` and `i--` also? – Afshin Mehrabani Oct 31 '12 at 10:25
13

Since none of the other answers seem to answer your specific question (more than half of them show C examples and discuss lower-level languages, your question is for JavaScript) I decided to write my own.

So, here you go:

Simple answer: i-- is generally faster because it doesn't have to run a comparison to 0 each time it runs, test results on various methods are below:

Test results: As "proven" by this jsPerf, arr.pop() is actually the fastest loop by far. But, focusing on --i, i--, i++ and ++i as you asked in your question, here are jsPerf (they are from multiple jsPerf's, please see sources below) results summarized:

--i and i-- are the same in Firefox while i-- is faster in Chrome.

In Chrome a basic for loop (for (var i = 0; i < arr.length; i++)) is faster than i-- and --i while in Firefox it's slower.

In Both Chrome and Firefox a cached arr.length is significantly faster with Chrome ahead by about 170,000 ops/sec.

Without a significant difference, ++i is faster than i++ in most browsers, AFAIK, it's never the other way around in any browser.

Shorter summary: arr.pop() is the fastest loop by far; for the specifically mentioned loops, i-- is the fastest loop.

Sources: http://jsperf.com/fastest-array-loops-in-javascript/15, http://jsperf.com/ipp-vs-ppi-2

I hope this answers your question.

A.M.K
  • 16,727
  • 4
  • 32
  • 64
  • 1
    It seems that your `pop` test seems only quite so fast because it is reducing the array size down to 0 for the majority of the loop - as far as I can tell. However to make sure things are fair I've designed this jsperf to create the array in the same way with each test - which seems to show `.shift()` as being the winner for my few browsers - not what I would have expected though :) http://jsperf.com/compare-different-types-of-looping – Pebbl Nov 02 '12 at 18:44
  • Upvoted for being the only one to mention ```++i``` :D – jaggedsoft Dec 04 '16 at 21:02
12

It depends on placement of your array in memory and the hit ratio of memory pages while you are accessing that array.

In some cases accessing array members in column order is faster than row order because of the increase in hit ratio.

dreamcrash
  • 47,137
  • 25
  • 94
  • 117
Akbar Bayati
  • 129
  • 1
  • 2
  • 1
    If only the OP had asked why traversing the same matrix in different orders can take different amounts of time.. – dcow Oct 31 '12 at 00:53
  • 1
    Considering that in Operating Systems that their memory management is based on Paging, when a process needs a data that is not in cached pages , occurs a page fault in OS and it must bring target page to CPU cache and replace with another page, therefore , causes overhead in processing that takes more time than when target page is in CPU cache. Suppose that we defined a large array that each row in it is bigger than page OS size and we access it in row order, in this case page fault ratio increases and result is slower than column order access to that array. – Akbar Bayati Oct 31 '12 at 05:07
  • Page faults aren't the same thing as cache misses. You only page fault if your memory got paged out to disk. Accessing multidimensional arrays in sequential order of how they're stored in memory is faster because of cache locality (using all bytes of a cache line when its fetched), not because of page faults. (unless your working set is too big for the computer you're using.) – Peter Cordes Aug 21 '15 at 04:48
10

The last time I bothered about it was when writing 6502 assembly (8-bit, yeah!). The big gain is that most arithmetic operations (especially decrements) updated a set of flags, one of them was Z, the 'reached zero' indicator.

So, at the end of the loop you just did two instructions: DEC (decrement) and JNZ (jump if not zero), no comparison needed!

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Javier
  • 60,510
  • 8
  • 78
  • 126
  • In case of JavaScript obviously it doesn't apply (since it runs on CPUs that don't have such op-codes). Most likely the real reason behind the `i--` vs `i++` is that with the former you don't introduce extra control variables in the loop's scope. See my answer below... – Pavel P Oct 30 '12 at 22:01
  • 1
    right, it really doesn't apply; but it's a very common C style, and it does looks cleaner to those of us that got used to that. :-) – Javier Oct 30 '12 at 22:42
  • x86 and ARM are both like 6502 in this respect. `dec/jnz` instead of `inc/cmp/jne` for the x86 case. You won't see an empty loop run any faster (both will saturate branch throughput), but counting down slightly reduces loop overhead. Current Intel HW prefetchers aren't bothered by memory access patterns that go in descending order, either. Older CPUs I think could track like 4 backwards streams and 6 or 10 forward streams, IIRC. – Peter Cordes Aug 21 '15 at 04:54
8

The way you're doing it now isn't faster (apart from it being an indefinite loop, I guess you meant to do i--.

If you want to make it faster do:

for (i = 10; i--;) {
    //super fast loop
}

of course you wouldn't notice it on such a small loop. The reason it's faster is because you're decrementing i while checking that it's "true" (it evaluates to "false" when it reaches 0)

peirix
  • 36,512
  • 23
  • 96
  • 126
7

for(var i = array.length; i--; ) is not much faster. But when you replace array.length with super_puper_function(), that may be significantly faster (since it's called in every iteration). That's the difference.

If you are going to change it in 2014, you don't need to think about optimization. If you are going to change it with "Search & Replace", you don't need to think about optimization. If you have no time, you don't need to think about optimization. But now, you've got time to think about it.

P.S.: i-- is not faster than i++.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Dmitry Isaev
  • 3,888
  • 2
  • 37
  • 49
7

To cut it short: There is absolutely no difference in doing this in JavaScript.

First of all, you can test it yourself:

Not only can you test and run any script in any JavaScript library, but you also have access to the whole bunch of previously written scripts, as well as the abilty to see differences between execution time in different browsers on different platforms.

So as far as you can see, there is no difference between performance in any environment.

If you want to improve performance of your script, things you can try to do:

  1. Have a var a = array.length; statement so that you will not be calculating its value each time in the loop
  2. Do loop unrolling http://en.wikipedia.org/wiki/Loop_unwinding

But you have to understand that the improvement you can gain will be so insignificant, that mostly you should not even care about it.

My own opinion why such a misconception (Dec vs Inc) appeared

A long, long time ago there was a common machine instruction, DSZ (Decrement and Skip on Zero). People who programmed in assembly language used this instruction to implement loops in order to save a register. Now this ancient facts are obsolete, and I am pretty sure you will not get any performance improvement in any language using this pseudo improvement.

I think the only way such knowledge can propagate in our time is when you read another's person code. See such a construction and ask why was it implemented and here the answer: "it improves performance because it compares to zero". You became bewildered of higher knowledge of your colleague and think to use it to be much smarter :-)

Community
  • 1
  • 1
Salvador Dali
  • 214,103
  • 147
  • 703
  • 753
  • Interesting, but for your tests running under firefox 16.0.2 on win7, the decrement loop was 29% slower... EDIT: Disregard that. Repeated tests proved inconclusive, there is a surprising amount of noise in my test results for subsequent runs. Not quite sure why. –  Oct 31 '12 at 01:39
  • Yeah I tried to account for that by closing everything else down and just running the tests. Still got wonky results. Very strange. –  Oct 31 '12 at 02:03
  • I think you missed the real point why going to zero is considered to be better in JavaScript. It's mostly because this way only one variable controls loop execution, e.g. this way optimizer/JITer has more room for improvement. Using `array.length` doesn't necessarily incur performance penalty, simply because JS virtual machine is smart enough to figure out if the array isn't modified by the loop's body. See my answer below. – Pavel P Oct 31 '12 at 06:52
  • 1
    nitpicking: this ancient fact (assembly language optimizations) is _not_ obsolete, just arcane. as in you don't need to know unless you really do. :-) – Javier Nov 21 '12 at 16:13
7

It can be explained by JavaScript (and all languages) eventually being turned into opcodes to run on the CPU. CPUs always have a single instruction for comparing against zero, which is damn fast.

As an aside, if you can guarantee count is always >= 0, you could simplify to:

for (var i = count; i--;)
{
  // whatever
}
searlea
  • 8,173
  • 4
  • 34
  • 37
  • 1
    Shorter source code doesn't necessarily mean it will be faster. Have you measured it? – Greg Hewgill Aug 27 '09 at 12:10
  • Ooops I missed this one. Nail on the head there chap. – Robert Aug 27 '09 at 12:20
  • 1
    I'd like to see the assembly sources where comparing against 0 is different. It's been a few years, but at one time I did a ton of assembly coding and I can't for the life of me think of a way to do a compare/test against 0 in a way that can't be equally as fast for any other integer. Yet, what you say does ring true. Frustrated that I can't figure out why! – Brian Knoblauch Aug 27 '09 at 12:25
  • Any references anywhere supporting this so I can do a bit of reading? – djdd87 Aug 27 '09 at 12:26
  • 7
    @Brian Knoblauch: If you use an instruction such as "dec eax" (x86 code) then that instruction automatically sets the Z (zero) flag which you can immediately test without having to use another compare instruction in between. – Greg Hewgill Aug 27 '09 at 12:29
  • @Brian For any other integer you'd have the overhead of pulling the value out of memory and loading it into a register. The Intel instruction set (as an example) has a shed-load of 'if zero' functionality for jumping and looping. Google for 'intel instruction set manual' if you want thousands of pages of documentation to wade through. – searlea Aug 27 '09 at 12:49
  • 1
    When interpretting Javascript, I doubt that opcodes are going to be the bottleneck, though. More likely to be that less tokens means the interpreter can process the source code faster. – Todd Owen Aug 27 '09 at 12:54
  • @Greg Hewgill - Thanks! I had completely forgotten that decrementing the accumulator sets flags too! – Brian Knoblauch Aug 27 '09 at 13:19
  • -1. Most Javascript engines don't actually generate machine code on the fly, so this is irrelevant. – Artelius Oct 08 '09 at 07:48
7

I made a comparison on jsbench.

As alestani pointed out, one thing that takes time in ascending loops, is to evaluate, for each iteration, the size of your array. In this loop:

for ( var i = 1; i <= array.length; i++ )

you evaluate .length each time you increment i. In this one:

for ( var i = 1, l = array.length; i <= l; i++ )

you evaluate .length only once, when you declare i. In this one:

for ( var i = array.length; i--; )

the comparison is implicit, it happens just before decrementing i, and the code is very readable. However, what can make a terrific difference, is what you put inside the loop.

Loop with call to function (defined elsewhere):

for (i = values.length; i-- ;) {
  add( values[i] );
}

Loop with inlined code:

var sum = 0;
for ( i = values.length; i-- ;) {
  sum += values[i];
}

If you can inline your code, instead of calling a function, without sacrificing legibility, you can have a loop an order of magnitude faster!


Note: as browser are becoming good at inlining simple functions, it really depends on how complex your code is. So, profile before optimizing, because

  1. The bottleneck may be elsewhere (ajax, reflow, ...)
  2. You may choose a better algorithm
  3. You may choose a better data structure

But remember:

Code is written for people to read, and only incidentally for machines to execute.

Spyryto
  • 1,107
  • 12
  • 17
  • +1 for this answer and for the benchmark. I've add forEach tests and reworked the benchmark to a standalone file runnable in browser as well as in Node. https://jsfiddle.net/hta69may/2/. For Node "Reverse loop, implicit comparison, inlined code" is the fastest. But testing in FF 50 shown curious results: not only the timings were almost 10 times less (!) but both "forEach" tests were as fast as "reverse loop". Maybe Node guys should use Mozilla's JS engine instead of V8? :) – Fr0sT Feb 14 '17 at 11:16
6

This is not dependent on the -- or ++ sign, but it depends on conditions you apply in the loop.

For example: Your loop is faster if the variable has a static value than if your loop check conditions every time, like the length of an array or other conditions.

But don't worry about this optimization, because this time its effect is measured in nanoseconds.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Arvind Kanjariya
  • 2,089
  • 1
  • 18
  • 23
  • multiple nanoseconds loops can become seconds ... it's never a bad idea to optimize when you have time for it – Buksy Oct 31 '12 at 08:27
5

++ vs. -- does not matter because JavaScript is an interpreted language, not a compiled language. Each instruction translates to more than one machine language and you should not care about the gory details.

People who are talking about using -- (or ++) to make efficient use of assembly instructions are wrong. These instruction apply to integer arithmetic and there are no integers in JavaScript, just numbers.

You should write readable code.

Salman A
  • 262,204
  • 82
  • 430
  • 521
4

It used to be said that --i was faster (in C++) because there is only one result, the decremented value. i-- needs to store the decremented value back to i and also retain the original value as the result (j = i--;). In most compilers this used up two registers rather than one which could cause another variable to have to be written to memory rather than retained as a register variable.

I agree with those others that have said it makes no difference these days.

Ant
  • 1,668
  • 2
  • 18
  • 35
  • benchmarks are all over the place: jsben.ch: `--i` is faster, https://jsben.ch/RpG0K. jsbench.me: `i--` is faster, https://jsbench.me/i2kkzuk4kl/1. measurethat.net: `--i` is faster, https://www.measurethat.net/Benchmarks/ShowResult/162675. – johny why Feb 10 '21 at 19:52
4

Sometimes making some very minor changes to the way that we write our code can make a big difference to how quickly our code actually runs. One area where a minor code change can make a big difference to execution times is where we have a for loop that is processing an array. Where the array is of elements on the web page (such as radio buttons) the change has the biggest effect but it is still worth applying this change even where the array is internal to the Javascript code.

The conventional way of coding a for loop to process an array lis like this:

for (var i = 0; i < myArray.length; i++) {...

The problem with this is that evaluating the length of the array using myArray.length takes time and the way that we have coded the loop means that this evaluation has to be performed every time around the loop. If the array contains 1000 elements then the length of the array will be evaluated 1001 times. If we were looking at radio buttons and had myForm.myButtons.length then it will take even longer to evaluate since the appropriate group of buttons within the specified form must first be located before the length can be evaluated each time around the loop.

Obviously we don't expect the length of the array to change while we are processing it so all of these recalculations of the length are just adding unnecessarily to the processing time. (Of course if you have code inside the loop that adds or removes array entries then the array size can change between iterations and so we can't change the code that tests for it)

What we can do to correct this for a loop where the size is fixed is to evaluate the length once at the start of the loop and save it in a variable. We can then test the variable to decide when to terminate the loop. This is much faster than evaluating the array length each time particularly when the array contains more than just a few entries or is part of the web page.

The code to do this is:

for (var i = 0, var j = myArray.length; i < j; i++) {...

So now we only evaluate the size of the array once and test our loop counter against the variable that holds that value each time around the loop. This extra variable can be accessed much faster than evaluating the size of the array and so our code will run much faster than before. We just have one extra variable in our script.

Often it doesn't matter what order we process the array in as long as all of the entries in the array get processed. Where this is the case we can make our code slightly faster by doing away with the extra variable that we just added and processing the array in reverse order.

The final code that processes our array in the most efficient way possible is:

for (var i = myArray.length-1; i > -1; i--) {...

This code still only evaluates the size of the array once at the start but instead of comparing the loop counter with a variable we compare it with a constant. Since a constant is even more effective to access than a variable and since we have one fewer assignment statement than before our third version of the code is now slightly more efficient than the second version and vastly more efficient than the first.

Kunwar Siddharth Singh
  • 1,676
  • 6
  • 33
  • 66
3

Well, I don't know about JavaScript, it should really be just a matter of re-evaluation array length and maybe something to do with the associative arrays (if you only decrement, it is unlikely new entries would need to be allocated - if the array is dense, that is. someone may optimize for that).

In low-level assembly, there is a looping instruction, called DJNZ (decrement and jump if non-zero). So the decrement and jump is all in one instruction, making it possibly ever-so-slightly faster than INC and JL / JB (increment, jump if less than / jump if below). Also, comparing against zero is simpler than comparing against another number. But all that is really marginal and also depends on target architecture (could make difference e.g. on Arm in a smartphone).

I wouldn't expect this low-level differences to have so great impact on interpreted languages, I just haven't seen DJNZ among the responses so I thought I would share an interesting thought.

the swine
  • 10,713
  • 7
  • 58
  • 100
  • For the record, `DJNZ` is an instruction in the 8051 (z80) ISA. x86 has `dec/jnz` instead of `inc/cmp/jne`, and apparently arm has something similar. I'm pretty sure this isn't the cause of the Javascript difference; that's from having more to eval in the loop condition. – Peter Cordes Aug 21 '15 at 05:03
3

Not a lot of time is consumed by i-- or i++. If you go deep inside the CPU architecture the ++ is more speedy than the --, since the -- operation will do the 2's complement, but it happend inside the hardware so this will make it speedy and no major difference between the ++ and -- also these operations are considered of the least time consumed in the CPU.

The for loop runs like this:

  • Initialize the variable once at the start.
  • Check the constraint in the second operand of the loop, <, >, <=, etc.
  • Then apply the loop.
  • Increment the loop and loop again throw these processes again.

So,

for (var i = Things.length - 1; i >= 0; i--) {
    Things[i]
}; 

will calculate the array length only once at the start and this is not a lot of time, but

for(var i = array.length; i--; ) 

will calculate the length at each loop, so it will consume a lot of time.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Omar Freewan
  • 2,678
  • 4
  • 25
  • 49
  • `var i = Things.length - 1; i >= 0; i--` will calculate length 1 time too. – Dmitry Oct 31 '12 at 10:29
  • 1
    I'm not sure what "`--` operation will do the 2's complement" means, but I assume it means that it will negate something. No, it doesn't negate anything on any architecture. Subtracting 1 is just as simple as adding 1, you just make a circuit that borrows rather than carries. – Olathe Aug 21 '13 at 13:25
3

First, i++ and i-- take exactly the same time on any programming language, including JavaScript.

The following code take much different time.

Fast:

for (var i = 0, len = Things.length - 1; i <= len; i++) { Things[i] };

Slow:

for (var i = 0; i <= Things.length - 1; i++) { Things[i] };

Therefore the following code take different time too.

Fast:

for (var i = Things.length - 1; i >= 0; i--) { Things[i] };

Slow:

for (var i = 0; i <= Things.length - 1; i++) { Things[i] };

P.S. Slow is slow only for a few languages (JavaScript engines) because of compiler's optimization. The best way is to use '<' instead '<=' (or '=') and '--i' instead 'i--'.

Dmitry
  • 14,306
  • 23
  • 105
  • 189
3

In very simple words

"i-- and i++. Actually, they're both takes the same time".

but in this case when you have incremental operation.. processor evaluate the .length every time variable is incremented by 1 and in case of decrement.. particularly in this case, it will evaluate .length only once till we get 0.

Ravi_Parmar
  • 12,319
  • 3
  • 25
  • 36
3

In many cases, this has essentially nothing to do with the fact that processors can compare to zero faster than other comparisons.

This is because only a few Javascript engines (the ones in the JIT list) actually generate machine language code.

Most Javascript engines build an internal representation of the source code which they then interpret (to get an idea of what this is like, have a look near the bottom of this page on Firefox's SpiderMonkey). Generally if a piece of code does practically the same thing but leads to a simpler internal representation, it will run faster.

Bear in mind that with simple tasks like adding/subtracting one from a variable, or comparing a variable to something, the overhead of the interpreter moving from one internal "instruction" to the next is quite high, so the less "instructions" that are used internally by the JS engine, the better.

Artelius
  • 48,337
  • 13
  • 89
  • 105
1

HELP OTHERS AVOID A HEADACHE --- VOTE THIS UP!!!

The most popular answer on this page does not work for Firefox 14 and does not pass the jsLinter. "while" loops need a comparison operator, not an assignment. It does work on chrome, safari, and even ie. But dies in firefox.

THIS IS BROKEN!

var i = arr.length; //or 10
while(i--)
{
  //...
}

THIS WILL WORK! (works on firefox, passes the jsLinter)

var i = arr.length; //or 10
while(i>-1)
{
  //...
  i = i - 1;
}
mrbinky3000
  • 4,055
  • 8
  • 43
  • 54
  • 2
    I just tried it on Firefox 14 and it worked fine. I have seen examples from production libraries that use `while (i--)` and which work across many browsers. Could there have been something weird about your test? Were you using a beta version of Firefox 14? – Matt Browne Jan 15 '13 at 15:05
1

This is just a guess, but maybe it's because it's easier for the processor to compare something with 0 ( i >= 0 ) instead of with another value ( i < Things.length).

Rorchackh
  • 2,113
  • 5
  • 22
  • 38
  • 3
    +1 Don't others have voted down. Although the repeated evaluation of .length is much more a problem than the actual inc/decrement, the check for the loop end might be important. My C compiler gives some warnings on loops like: "remark #1544-D: (ULP 13.1) Detected loop counting up. Recommend loops count down as detecting zeros is easier" – harper Oct 30 '12 at 12:10
1

Wouldn't the compiler cache .length, and therefore it makes no difference if you are comparing 0 or .length? I guess this is very specific to the compiler or interpreter you are dealing with.

I would say if you are using a well optimised compiler or interpreter then you shouldn't worry about this, it is for the language developers to worry about.

Daniel
  • 629
  • 6
  • 17
1

The best approach to answering this sort of question is to actually try it. Set up a loop that counts a million iterations or whatever, and do it both ways. Time both loops, and compare the results.

The answer will probably depend on which browser you are using. Some will have different results than others.

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
  • 4
    That still wouldn't answer his question on _why_ it's faster. He'd just get a benchmark, without any knowledge of why it is that way... – peirix Aug 27 '09 at 12:23
  • 3
    That's true. However, without knowing the exact implementation of each Javascript engine in each browser, it's nearly impossible to answer the "why" part. A lot of the answers here throw around anecdotal recommendations like "use predecrement instead of postdecrement" (a C++ optimisation trick) and "compare against zero" which might be true in native code compiled languages but Javascript is pretty far from the bare metal of the CPU. – Greg Hewgill Aug 27 '09 at 12:27
  • 4
    -1 I completely disagree that the best approach is to try it. A couple examples don't replace collective knowledge, and that's the whole point of forums like this one. – Christophe Jan 30 '12 at 18:41
1

Love it, lots of marks up but no answer :D

Simply put a comparison against zero is always the fastest comparison

So (a==0) is actually quicker at returning True than (a==5)

It's small and insignificant and with 100 million rows in a collection it's measurable.

i.e on a loop up you might be saying where i <= array.length and be incrementing i

on a down loop you might be saying where i >= 0 and be decrementing i instead.

The comparison is quicker. Not the 'direction' of the loop.

Robert
  • 1,835
  • 4
  • 25
  • 30
  • There is no answer to the question as stated because Javascript engines are all different and the answer depends on exactly which browser you're measuring it on. – Greg Hewgill Aug 27 '09 at 12:14
  • No it's fundamentally accepted comparisons against zero are the quickest. Although your statements are correct as well the golden rule of comparing against zero is absolute. – Robert Aug 27 '09 at 12:18
  • 4
    That's true *only* if the compiler chooses to make that optimisation, which is certainly not guaranteed. The compiler might generate exactly the same code for (a==0) and (a==5), except for the value of the constant. A CPU won't compare against 0 any more quickly than against any other value, if both sides of the comparison are variables (from the point of view of the CPU). Generally only native code compilers have the opportunity to optimise at this level. – Greg Hewgill Aug 27 '09 at 12:24
0

Using the prefix increment operator is somewhat faster. With the postfix, the compiler must retain the previous value as the result of the expression.

for (var i = 0; i < n; ++i) {
  do_stuff();
}

A smart interpreter or compiler will see that the result of i++ is not used and not store the result of the expression, but not all js engines do.

Jeff Ober
  • 4,967
  • 20
  • 15
  • 1
    How do you know that the prefix operation is "somewhat" faster? Have you measured it? – Greg Hewgill Aug 27 '09 at 12:13
  • Really, it depends on the implementation. Without compiler optimization, it requires less work, since it need not keep a copy of the old value to return as the result of the expression. – Jeff Ober Aug 27 '09 at 14:30
0

I want to contribute to this thread the fastest loop in JavaScript that is cross-browser ! This loop yields over 500% improvement compared to the reverse while loop.

My Blog: Fastest Loop in JavaScript

Milan Adamovsky
  • 1,519
  • 1
  • 10
  • 5
-2

The fastest way for decrement mode:

var iteration = 10000000;
    while(iteration > 0){
        iteration--;
    }

FASTER THAN:

var iteration = 10000000;
    while(iteration--);

Javascript micro optimisation test

putto
  • 1
  • i think you want to start at `10000000 - 1`, and then test for `iteration > -1`. But that test for `-1` might slow things down. – johny why Feb 08 '21 at 00:44