Reputation: 29
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
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]
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.
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 realloc
ated 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