for loop versus if condition - javascript

There are two alternatives I have for executing a piece of code. The code basically resets all the values in three arrays. Two of them are int arrays and one is boolean.
Choice 1
for (i = 0; i < array1.length; i++)
array1[i] = 0;
for (i = 0; i < array2.length; i++)
array2[i] = 0;
for (i = 0; i < array3.length; i++)
array3[i] = false;
Choice 2
int limit = <assign the greatest of the array lengths>
for (i = 0; i < limit; i++)
{
if (i < array1.length)
array1[i] = 0;
if (i < array2.length)
array2[i] = 0;
if (i < array3.length)
array3[i] = false;
}
Which of these would be faster? Given that the arrays can have varying lengths and have no relationship with each other.
There is a real good discussion here. The answer listed first explains quiet well what arrays actually mean in javascript. For those interested to check it out!

This version is almost certainly going to be faster. It is also easier to read and shorter, which are both much more important attributes than speed (99+% of the time).
for (i = 0; i < array1.length; i++)
array1[i] = 0;
for (i = 0; i < array2.length; i++)
array2[i] = 0;
for (i = 0; i < array3.length; i++)
array3[i] = false;
In general, it is faster to access data that is close in memory to data that you accessed recently.
This version also does not suffer from additional branching you would get in the second version.
A sufficiently advanced compiler would transform the second version into the first.
Benchmarking: Micro-benchmarks are 100% useless without profiling your entire program first. Since I don't think the performance measurements are useful, I am not providing them.

function reset_array(array, value) {
var len = array.length;
array.length = 0;
while (len--) array.push(value);
}
reset_array(array1, 0);
reset_array(array2, 0);
reset_array(array3, false);

Related

Redefining variables for multiple for loops, good or bad practice?

I primarily program in AS3 at work, where the lowest scope is the function and not the executing block. This means the following code works fine
for (var i:int = 0; i < 3; i++) {trace(i);}
but this code results in a warning because apparently i is being redefined.
for (var i:int = 0; i < 3; i++) {trace(i);}
for (var i:int = 0; i < 3; i++) {trace(i);}
That means that I generally have to do something like this to avoid warnings from the compiler (and reprimands from my superiors about "bad practice").
var i:int;
for (i = 0; i < 3; i++) {trace(i);}
for (i = 0; i < 3; i++) {trace(i);}
I've been experimenting in TypeScript lately and I find the let concept for defining executing block scopes very practical. I discussed this with a coworker and he insisted that using let within a loop would be bad practice since the variables get redefined every loop.
Is there a fundamental difference performance-wise between the following two methods in TypeScript?
for (let i:number = 0; i < 3; i++) {console.log(i)}
for (let i:number = 0; i < 3; i++) {console.log(i)}
and
let i:number
for (i = 0; i < 3; i++) {console.log(i)}
for (i = 0; i < 3; i++) {console.log(i)}
When you define a variable with let, the variable is local to the scope.
So when you do this
for (let i:number = 0; i < 3; i++) {console.log(i)}
i is scoped into the loop for.
Is not a bad practice to declare i into each loop.
For exemple if you loop on two different array, you can create two loop to iterate it.
If you use an specific iteraztor name for each you can have code like :
const arrFoo: Array<number> = [0, 1, 2];
const arrBar: Array<number> = [0, 1, 2];
for (let iteratorFoo:number = 0; iteratorFoo < arrFoo.length; i++) {console.log(iteratorFoo);}
for (let iteratorBar:number = 0; iteratorBar < arrBar.length; i++) {console.log(iteratorBar);}
In this case it's a good practice to declare two differents iterator.
Unless you use the same i in each loop.
Like :
let i:number
for (i = 0; i < 3; i++) {console.log(i)} // show 0, 1, 2
for (; i < 6; i++) {console.log(i)} // show 3, 4, 5
And for the performance-wise, the difference is clearly not noticeable to a human.
Edit based on comment :
What about in a case where the loop iterates tens of thousands of times?
for ([initialization]; [condition]; [final-expression])
initialization
An expression (including assignment expressions) or variable declaration evaluated once before the loop begins. Typically used to initialize a counter variable. This expression may optionally declare new variables with var or let keywords. [...]. Variables declared with let are local to the statement.
Reference
So the initialization is evaluated once, even if your loop iterates tens of thousands of times.

Loop guard optimization

A number of years ago I read a very simple article about loop optimization. In particular, if you have to iterate over a list in Java you can put the guard in the initialization in order to avoid a method call in each iteration:
for (int i = 0; i < list.size(); ++i)
becomes:
for (int i = 0, len = list.size(); i < len; ++i)
Now, I'm working with Javascript where the Array lenght is stored in a variable. So, I was wondering if there is a difference between:
for (var i = 0; i < list.length; ++i)
and:
for (int i = 0, len = list.length; i < len; ++i)
Moreover, I read that prefix increment is preferred since it doesn't evaluate to the value of the expression, right?

does caching array length for a loop condition affect performance?

Is there a big difference between
for (var i = 0, c = data.length; i < c; i++) {
}
And
for (var i = 0; i < data.length; i++) {
}
What is the difference?
In the first code, the length of the array(or array-like collection) is calculated only once and it it cached. So, the length is not recalculated per each iteration.
While in the second code, the length is calculated per iteration.
You can say that caching the length will be slightly faster than recalculating the length. This difference will be very very small that you can neglect this for smaller arrays. But for huge array, the difference could be significant.
Which way to use totally depend on the use case.
If the array length is updated inside the loop must use the second code.
for (var i = 0; i < data.length; i++) {
// Useful when the data length is altered in here
}
each time you are calculating data.length in
for (var i = 0, c = data.length; i < c; i++) {}

Objects from same array using for loop with j = i + 1

I have a loop to check collision between objects in my game, all the objects are collected in the same Array. I use a code like this to match every object with eachother:
for (var i = 0; i < objs.length; i++) {
for (var j = i + 1; j < objs.length; j++) {
collision(objs[i], objs[j]);
}
}
Now this does not seem to actually perform all collisions with eachother, I've noticed that it skips some too..
Then I came up with this solution:
for (var i = 0; i < objs.length; i++) {
for (var j = 0; j < objs.length; j++) {
if (j != i) {
collision(objs[i], objs[j]);
}
}
}
This solution seem to not have any problems, but I wonder if there is any kinda way to not have to use the if (j != i) statement, or is there maybe a totally different solution?
Soo, who's correct eh..?
It depends on the definition of collision in your game.
If collision is a symmetric function (i.e. A collides with B if, and only if, B collides with A), then use:
for (var i = 0; i < objs.length; i++) {
for (var j = i + 1; j < objs.length; j++) {
collision(objs[i], objs[j]);
}
}
because there's no need to check (B,A) if you checked (A,B) before.
But if it is possible to make A collide with B without making B collide with A, or vice versa, then you must check all possible different pairs, so use
for (var i = 0; i < objs.length; i++) {
for (var j = 0; j < objs.length; j++) {
if (j != i) {
collision(objs[i], objs[j]);
}
}
}

Why is iterating through an array backwards faster than forwards

Given this code:
var arr = [];
for (var i = 0; i < 10000; ++i)
arr.push(1);
Forwards
for (var i = 0; i < arr.length; ++i) {}
Backwards
for (var i = arr.length - 1; i >= 0; --i) {}
Hard-coded Forward
for (var i = 0; i < 10000; ++i) {}
Why is backwards so much faster?
Here is the test:
http://jsperf.com/array-iteration-direction
Because your forwards-condition has to receive the length property of your array each time, whilst the other condition only has to check for "greater then zero", a very fast task.
When your array length doesn't change during the loop, and you really look at ns-perfomance, you can use
for (var i=0, l=arr.length; i<l; i++)
BTW: Instead of for (var i = arr.length; i > 0; --i) you might use for (var i = arr.length; i-- > 0; ) which really runs through your array from n-1 to 0, not from n to 1.
Because in the first form you are accessing the property length of the array arr once for every iteration, whereas in the second you only do it once.
If you want to have them at same pace, you can do that for forward iteration;
for(var i=0, c=arr.length; i<c; i++){
}
So, your script won't need to take length of array on everystep.
I am not entirely sure about this, but here is my guess:
For the following code:
for (var i = 0; i < arr.length; ++i) {;
}
During runtime, there is an arr.length calculation after each loop pass. This may be a trivial operation when it stands alone, but may have an impact when it comes to multiple/huge arrays. Can you try the following:
var numItems = arr.length;
for(var i=0; i< numItems; ++i)
{
}
In the above code, we compute the array length just once, and operate with that computed number, rather than performing the length computation over and over again.
Again, just putting my thoughts out here. Interesting observation indeed!
i > 0 is faster than i < arr.length and is occurring on each iteration of the loop.
You can mitigate the difference with this:
for (var i = 0, len = arr.length; i < len; ++i) {;
}
This is still not as fast as the backwards item, but faster than your forward option.
do it like below, it will perform in same way. because arr.length takes time in each iteration in forward.
int len = arr.length;
forward
for (var i = 0; i < len; ++i) {
}
backward
for (var i = len; i > 0; --i) {
}
And these are equally good:
var arr= [], L= 10000;
while(L>-1) arr[L]= L--;
OR
var arr= [], i= 0;
while(i<10001) arr[i]=i++;

Categories

Resources