Is the condition in the for loop evaluated in every loop? - javascript

I have a situation like:
for(var i = 0; i < a + b; ++i)
// code that doesn't affect a and b
Should I worry about the addition been performed in every iteration? Or JavaScript (its parser?) is smart enough to understand that a + b is constant?
In other words, should I do that like this:
var end = a + b;
for(var i = 0; i < end; ++i)
// code
or will this waste a line of code?
Well, actually what I worry about is not that one line of code, BUT the fact that I am thinking about it every time I face a situation like this in JavaScript! Also, today it's an addition, tomorrow it may be something else, like the square root of it, so I think it's important!

The condition is going to be evaluated each time.
From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for
for ([initialization]; [condition]; [final-expression])
statement
condition: An expression to be evaluated before each loop iteration. If
this expression evaluates to true, statement is executed. This
conditional test is optional. If omitted, the condition always
evaluates to true. If the expression evaluates to false, execution
skips to the first expression following the for construct.
(Italic is mine)
There could or could not be an optimization on a sub-expression of the condition, depending on the engine: when you have a similar doubt the fastest thing you can do is to setup a test and measure performances.
According to this test for example the two versions take the same time on the latest Chrome and Firefox.
However, the rule of the thumb about this kind of optimizations is: do not prematurely optimize. From Program optimization on Wikipedia:
"We should forget about small efficiencies, say about 97% of the time:
premature optimization is the root of all evil. Yet we should not pass
up our opportunities in that critical 3%"
Knuth, Donald (December 1974). "Structured Programming with go to
Statements". ACM Journal Computing Surveys 6 (4): 268. CiteSeerX:
10.1.1.103.6084.
Write functionally correct code, without worrying about such small or doubt performance issues. When executing, if you find you have a performances problem, dig in and optimize.
TL; DR
You shouldn't be worried about this, the performance impact is likely to be minimal, and modern javascript engines seem to optimize this anyway.
But if you are still worried, writing a line of code doesn't seem to me a big waste. So why don't just you do that, and stop thinking about it?

It's better to define the constant like this :
for(var i = 0, end = a + b; i < end; ++i)
Optimization way
You can write your loop like this :
for(var i = a + b; i--;)
This is for me the more optimized but i is descending and not ascending
More example
A simple example to understand. If you create your loop like this :
for(var i = 0; i < array.length; ++i) {
array.push('value'); // infinite loop
}
array.length is evaluated on every iteration and you can create an infinite loop with array.push().

It will be evaluated for each loop but a simple addition operation such as the a + b that you used in the example is generally such an easy operation that you won't see a noticeable difference one way or the other. That being said, it is a better idea to just add a and b together before the loop as in your second example.

Related

Javascript for loop optimization

The classic for loop structure in Javascript is something like this:
// original loop
for (var i = 0; i < items.length; i++){
process(items[i]);
}
But I have recently came across an article about how we can optimize loops in JS (here) that gives an intersting optimized reverse version of a foor loop as follows:
// minimizing property lookups and reversing
for (var i = items.length; i--; ){
process(items[i]);
}
Suppose that we have an array like let v = ["C", "P", "L", "T"] so when you run the above for loop for this array:
for (let i = v.length; i--;) {
console.log(v[i]);}
It will log the array items in reverse order. The confusing thing is this version of a for loop doesn't have a pretest condition or it seems so at least so how come that it works nevertheless and how it knows it should stop decrementing i when it reaches 0?
The important thing to recognize here is that the test to see if the loop should stop executing - the second part of a for loop declaration, the i-- - evaluates to an expression which can be tested for truthyness/falseyness:
let i = 2;
console.log(i--);
console.log(i--);
console.log(i--);
The i-- not only decrements the variable in i, but it also evaluates to an expression equivalent to i before the decrement occurs.
Since the test (the i--) is carried out on every iteration, i is decremented on every iteration, and it stops once the iteration for i = 0 finishes.
But this is a really really strange thing to want to do. As commenters have noted, it looks exceedingly odd and is hard to read and understand.
Performance is rarely an issue worth worrying about in 99% of code. Better to optimize for code clarity and readability. If you later run a performance test and see that a particular part of the code is running too slowly, go ahead and try to fix it - but reversing a for loop like this is almost certainly not a bottleneck, so you're just making the code harder to read for no real benefit.
The syntax of the for is the following:
for ([initialization]; [condition]; [finale_expression])
instruction
In your sample, there is no finale_expression so the i-- is both the condition and the finale_expression. That means the for will loop while i is true, which is the case while it's greater than 0.

What are the pros and cons to assigning the end point of a for loop?

In various languages (I'm going to use JavaScript here, but I've seen it done in PHP and C++ and probably elsewhere), there seem to be a couple of ways of constructing a simple for loop. Version 1 is like:
var top = document.getElementsByTagName("p");
for (var i = 0; i < top.length; i++) {
...do something
}
Whereas elsewhere I've seen people construct the for loop like:
for (var i = 0, ii = top.length; i < ii; i++)
It seems like people do it without rhyme or reason - the same programmer will do both in the same script. Is there any reason to do one and not the other?
Cheers
In some languages, getting the length of an array or string may be an expensive operation. Since it doesn't change during the loop, doing it every time you test whether the iteration variable has reached the end is wasteful. So it's more efficient to get the length once and save it in a variable.
An example would be iterating over a string in C. In C, strlen() is an O(n) operation, because it has to search the char array looking for the terminating 0 element. If you wrote:
for (i = 0; i < strlen(string); i++)
your loop would be O(n2).
In languages like Javascript, getting the length is inexpensive, but programmers stick with their old habits. And programmers who have never even used those other languages learn idioms from the ones who did, so they use this coding style without even knowing the reason.
See this YouTube video for an explanation of how this type of thing happens in communities:
https://www.youtube.com/watch?v=b4vJ8l2NfIM

For Loop optimization in Javascript

So i have been taking a Computer science course that uses C+ to teach programming concepts with. today i learned a new concept that i was not sure applied to JS, in which there are system resources expended each time a string.length is calculated. It seems like a tiny matter but it got me thinking about huge arrays and how that could add up. Check out this example and let me know if loop #2 is indeed more efficient than the first and thanks:
var weekDay = ["Monday", "Tuesday", "Wednesday"];
//for loop #1
for(i=0; i<weekDay.length; i++){
//code code code
;}
//for loop #2
for(i=0; var n=weekDay.length; i<n; i++){
//code code code
;}
The second approach is faster, but not by much. Also, there is a small syntax error
for( var i = 0, n = weekDay.length; i < n; i++ ){ ... }
This is rather common in javascript code. Please note the importance in declaring all of your variables with var so that they do not step on the wrong scope.
You can see this js performance test here: http://jsperf.com/forloopiterator which shows the results being 24% faster when using the second approach.
First of all, premature optimization is the root of all evil.
Secondly; you are completely correct that loop #2 is more efficient.
Loop #1 would do calculate the length of weekDay for every iteration of the loop. This means it would calculate the length 10,000 times in a 10,000 length array.
Loop #2 would calculate the length of weekDay and set the variable n to be the result, and hence we keep the length in a variable rather than recalculating it for every iteration.
Read more about why premature optimization is bad.
This question has been asked a few times...
Is optimizing JavaScript for loops really necessary?
I found the following link very helpful. Basically it depends on browser version and vendor.
In some cases e.g. IE yes #2 is much faster
http://jsperf.com/loop-iteration-length-comparison-variations
I would always pre-cache the length explicity, i.e.
var n = weekDay.length;
var i;
for(i=0;i<n; i++){
do_something;
}
A much clearer approach, as all variables definitions are 'hoisted' to the top of the function anyway.

In a loop, do any operations in the end-condition get evaluated in every iteration?

In the following code:
for (var i = 0; i < object.length; i++){
....
}
does the operation object.length get evaluated every time in the iteration?
It would make most sense that the language will evaluate this once and save the result. However, I was reading some code where someone evaluated the operation before the loop started and stored it in a variable that was used in the end-condition.
Do different languages handle this differently? Any specific info for Javascript?
It obviously depends on the language. For JavaScript, the spec (ECMAScript ยง12.6.3) requires it always be evaluated each time. As an optimization, a specific JavaScript runtime could skip one or more of the length calls, if it could prove that the result would not change.
Completely depends on the language and (possibly) on what's in the loop. The compiler/interpreter may or may not be able to determine with certainty that the "length" property won't be changed by something in the loop.
In Javascript, it's a safe bet that it'll be re-evaluated. A simple property reference like that probably isn't that bad, but something like a function call could be a performance problem. edit To clarify, by "a function call" I mean code of any form that computes the loop termination condition in any way expensive enough to make you feel bad about doing it on each iteration.
Thus (pardon my jQuery),
for (var i = 0; i < $('.foo').length; ++i) { /* ... */ }
would involve a traversal of the whole DOM on each iteration.
The condition has to be re-evaluated at each iteration of the loop because in theory the value could have changed inside the loop body.
A smart compiler could automatically optimize for this case, but performing static analysis to determine that the length will not change inside the loop is extremely difficult in JavaScript. For this reason, you can say that in most cases object.length will indeed be reevaluated in each iteration.
On the other hand, it's often simpler for the programmer to reason out that the length will certainly not change, and if you're really (I mean, really) worried about performance, you could pre-compute and store the length before the loop starts.
If order doesn't matter to you, iterate backwards. You don't need the messy temporary variable holding the length in this case. The start condition of the loop is only evaluated once (obviously, it'd be pointless re-evaluating it once the loop has already started!). Using an example from an early response:
for (var i = $('.foo').length - 1; i >= 0; i--) { /* ... */ }
I know I'm answering this long after it was asked, but it's still showing high in Google search results for related queries and none of the existing answers seem to suggest this alternative approach.
In some languages this depends on the level of optimization you have configured at build-time. I believe in C++, for example, marking a field as volatile will force re-evaluation. Check out these links:
http://en.wikipedia.org/wiki/Loop_unwinding
http://msdn.microsoft.com/en-us/library/12a04hfd.aspx
In Javascript it does get evaluated every time. You can get around it by setting a "max" variable in the first part of the loop:
for (var i=0, imax=object.length; i<imax; i++) {
// statements
}
Yes it gets calculated each iteration ..
why not test it ?
var loop = 5;
for (var i = 0; i< loop; i++)
{
alert(i + ' of ' + loop);
loop--;
}
live at http://jsfiddle.net/MSAdF/

Is it faster access an javascript array directly?

I was reading an article: Optimizing JavaScript for Execution Speed
And there is a section that says:
Use this code:
for (var i = 0; (p = document.getElementsByTagName("P")[i]); i++)
Instead of:
nl = document.getElementsByTagName("P");
for (var i = 0; i < nl.length; i++)
{
p = nl[i];
}
for performance reasons.
I always used the "wrong" way, according the article, but, am I wrong or is the article wrong?
"We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil."
--Donald Knuth
Personally i would use your way because it is more readable and easier to maintain. Then i would use a tool such as YSlow to profile the code and iron out the performance bottlenecks.
If you look at it from a language like C#, you'd expect the second statement to be more efficient, however C# is not an interpreter language.
As the guide states: your browser is optimized to retrieved the right Nodes from live lists and does this a lot faster than retrieving them from the "cache" you define in your variable. Also you have to determine the length each iteration, with might cause a bit of performance loss as well.
Interpreter languages react differently from compiled languages, they're optimized in different ways.
Good question - I would assume not calling the function getElementsByTagName() every loop would save time. I could see this being faster - you aren't checking the length of the array, just that the value got assigned.
var p;
var ps = document.getElementsByTagName("P");
for (var i = 0; (p=ps[i]); i++) {
//...
}
Of course this also assumes that none of the values in your array evaluate to "false". A numeric array that may contain a 0 will break this loop.
Interesting. Other references do seem to back up the idea that NodeLists are comparatively heavyweight.
The question is ... what's the overhead? Is it enough to bother about? I'm not a fan of premature optimisation. However this is an interesting case, because it's not just the cost of iteration that's affected, there's extra overhead as the NodeList must be kept in synch with any changes to the DOM.
With no further evidence I tend to believe the article.
No it will not be faster. Actually it is nearly totally nonsense since for every step of the for loop, you call the "getElementsByTagName" which, is a time consuming function.
The ideal loop would be as follows:
nl = document.getElementsByTagName("P");
for (var i = nl.length-1; i >= 0; i--)
{
p = nl[i];
}
EDIT:
I actually tested those two examples you have given in Firebug using console.time and as everyone have though the first one took 1ms whereas the second one took 0ms =)
It makes sense to just assign it directly to the variable. Probably quicker to write as well. I'd say that the article might have some truth to it.
Instead of having to get the length everytime, check it against i, and then assign the variable, you simply check if p was able to be set. This cleans up the code and probably is actually faster.
I typically do this (move the length test outside the for loop)
var nl = document.getElementsByTagName("p");
var nll = nl.length;
for(var i=0;i<nll;i++){
p = nl[i];
}
or for compactness...
var nl = document.getElementsByTagName("p");
for(var i=0,nll=nl.length;i<nll;i++){
p = nl[i];
}
which presumes that the length doesn't change during access (which in my cases doesn't)
but I'd say that running a bunch of performance tests on the articles idea would be the definitive answer.
The author of the article wrote:
In most cases, this is faster than caching the NodeList. In the second example, the browser doesn't need to create the node list object. It needs only to find the element at index i at that exact moment.
As always it depends. Maybe it depends on the number of elements of the NodeList.
For me this approach is not safe if the number of elemets can change, this could cause and index out of bound.
From the article you link to:
In the second example, the browser doesn't need to create the node list object. It needs only to find the element at index i at that exact moment.
This is nonsense. In the first example, the node list is created and a reference to it is held in a variable. If something happens which causes the node list to change - say you remove a paragraph - then the browser has to do some work to update the node list. However, if your code doesn't cause the list to change, this isn't an issue.
In the second example, far from not needing to create the node list, the browser has to create the node list every time through the loop, then find the element at index i. The fact that a reference to the node list is never assigned to a variable doesn't mean the list doesn't have to be created, as the author seems to think. Object creation is expensive (no matter what the author says about browsers "being optimized for this"), so this is going to be a big performance hit for many applications.
Optimisation is always dependant on the actual real-world usage your application encounters. Articles such as this shouldn't be seen as saying "Always work this way" but as being collections of techniques, any one of which might, in some specific set of circumstances, be of value. The second example is, in my opinion, less easy to follow, and that alone puts it in the realm of tricksy techniques that should only be used if there is a proven benefit in a specific case.
(Frankly, I also don't trust advice offered by a programmer who uses a variable name like "nl". If he's too lazy to use meaningful names when writing a tutorial, I'm glad I don't have to maintain his production code.)
It is worthless to discuss theory when actual tests will be more accurate, and by comparing both the second method was clearly faster.
Here is sample code from a benchmark test
var start1 = new Date().getTime();
for (var j= 0; j < 500000; j++){
for (var i = 0; (p = document.getElementsByTagName("P")[i]); i++);
}
var end1 = new Date().getTime() - start1;
var start2 = new Date().getTime();
for (var j= 0; j < 500000; j++){
nl = document.getElementsByTagName("P");
for (var i = 0; i < nl.length; i++)
{
p = nl[i];
}
}
var end2 = new Date().getTime() - start2;
alert("first:" + end1 + "\nSecond:" + end2);
In chrome the first method was taking 2324ms while the second took 1986ms.
But note that for 500,000 iterations there was a difference only 300ms so I wouldn't bother with this at all.

Categories

Resources