Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is filling a new Array so much faster with a while loop?

I was considering ways to create arrays containing a default value using native methods and ended up with

function pushMap(length, fill){
    var a = [], b = [];
    a.length = length;
    b.push.apply(b,a);
    return b.map(function(){return fill;});
}

Expecting it to be 2 or 3 times slower than a while loop, as the native methods have to loop twice whereas while loops only once, so I compared it on jsperf against

function whileLengthNew(len, val) {
    var rv = new Array(len);
    while (--len >= 0) {
        rv[len] = val;
    }
    return rv;
}

and it is actually 18 to 27 times slower (tested with Google Chrome on Ubuntu, browsers/OSs welcome).

What is happening that causes such a big difference?

like image 533
Paul S. Avatar asked Sep 17 '12 18:09

Paul S.


People also ask

Is arrays fill faster than a loop?

fill(0); The Array. fill() method would take ~210-250ms to fill an array of size 10000000, while the for loop would take ~70-90ms.

Which array method is faster?

In case of multiple iterations of the loop, and where the size of array is too large, for loop is the preference as the fastest method of elements' iteration. While loops perform efficient scaling in case of large arrays.

Why filling an array from the front is slow?

Because filling array from front means the existing objects need to be pushed to the back first before adding the item at index 0? Thanks. That could be the possible reason. Inserting from front would require shifting rest of elements.

Which loop is faster?

For loop (forward and reverse) The traditional for loop is the fastest, so you should always use that right? Not so fast - performance is not the only thing that matters. Code Readability is usually more important, so default to the style that fits your application.


1 Answers

I would expect that this is due to two major factors:

  1. Memory allocation -- whileLengthNew creates an array of the correct size first, and then operates on it, pushMap creates the final array one element at a time with map. This may cause multiple allocations, especially if the source array is large. (The way that you create the initial a and b arrays is basically irrelevant, since map is building up a new array to return anyway -- it doesn't actually change anything in b)

  2. Function call overhead -- in your call to map, you are calling a function for every element of the array. This involves quite a lot of overhead; setting up activation records and scope chains, stack manipulation, and passing the return value back. -- all of this to access a variable which is constant within the function. On top of that, you have set up a closure, so even accessing the fill variable is slower than it is in the whileLengthNew version.

like image 94
Ian Clelland Avatar answered Oct 21 '22 14:10

Ian Clelland