JayL
JayL

Reputation: 29

Different ways to create Javascript arrays

I want to understand the performance difference for constructing arrays. Running the following program, I am puzzled by the output below:

Time for range0: 521
Time for range1: 149
Time for range2: 1848
Time for range3: 8411
Time for range4: 3487

I don't understand why 3 takes longer than 4, while 1 takes shorter than 2. Also, seems the map function is very inefficient; what is the use of it?


function range0(start, count) {
    var arr = [];
    for (var i = 0; i < count; i++) {
        arr.push(start + i);
    }
    return arr;
}

function range1(start, count) {
    var arr = new Array(count);
    for (var i = 0; i < count; i++) {
        arr[i] = start + i;
    }
    return arr;
}

function range2(start, count) {
    var arr = Array.apply(0, Array(count));
    for (var i = 0; i < count; i++) {
        arr[i] = start + i;
    }
    return arr;
}

function range3(start, count) {
    var arr = new Array(count);
    return arr.map(function(element, index) {
        return index + start;
    });
}

function range4(start, count) {
    var arr = Array.apply(0, Array(count));
    return arr.map(function(element, index) {
        return index + start;
    });
}

function profile(range) {
    var iterations = 100000,
        start = 0, count = 1000,
        startTime, endTime, finalTime;

    startTime = performance.now();

    for (var i = 0; i < iterations; ++i) {
        range(start, count);
    }

    endTime = performance.now();

    finalTime = (endTime - startTime);
    console.log(range.name + ': ' + finalTime + ' ms');
}

[range0, range1, range2, range3, range4].forEach(profile);

Upvotes: 0

Views: 344

Answers (1)

Matheus Moreira
Matheus Moreira

Reputation: 17020

I don't understand why 3 takes longer than 4

Me neither. It is a surprising result, given my superficial analysis and the results I obtained by profiling the code. On my computer running Google Chrome 50, range4 is twice as slow compared to range3.

I'd have to study the Javascript implementation you are using in order to figure out why that happens.

while 1 takes shorter than 2.

range1 executes faster because it uses a loop and optimizes memory allocations, while range2 uses functions and does unnecessary memory allocations.

Also, seems the map function is very inefficient; what is the use of it?

The map function is used to compute a new Array based on the values of an existing one.

[1, 2, 3, 4, 5].map(number => number * number);
// [1, 4, 9, 16, 25]

On my computer

Time for range0: 783
Time for range1: 287
Time for range2: 10541
Time for range3: 14981
Time for range4: 28243

My results reflect my expectations regarding the performance of each function.

A superficial analysis of each function

  • range0

    Creates an Array and populates it via a loop. It is the most simple and straightforward code possible. I suppose it could be understood as the baseline for performance comparison.

  • range1

    Uses the Array constructor with a length parameter. This greatly optimizes the underlying memory allocation required to store the elements. Since the exact number of elements is known beforehand, the memory does not have to be reallocated as the number of elements grows; the exact amount of memory needed to store all elements can be allocated exactly once, when the Array is instantiated.

  • range2

    Applies an empty arguments list to the constructor function, with this set to the number 0. This is semantically equivalent to Array() – the fact the arguments list was created with a count parameter has no bearing on the result of the function application. In fact, it needlessly wastes time allocating memory for an empty arguments list.

    You probably meant to use call:

      Array.call(null, count)
    
  • range3

    Like range1, but uses map with a function instead of a loop. The initial memory allocation is optimized, but the overhead of calling the function count times is likely to be huge.

    In addition, map generates a new Array instance. Since that instance also has count elements, it would make sense to optimize that memory allocation as well, however it is unclear to me whether that actually happens. Nevertheless, two separate memory allocations are taking place, instead of just one as in range1.

  • range4

    Combines all the inefficiencies of range2 and range3.

    Amazingly, it executes faster than range3 on your computer. It's unclear to me why that happened. I suppose one would have to investigate your Javascript particular implementation in order to figure it out.

Upvotes: 1

Related Questions