Sunday 10 February 2013

Loops in Java Script

There are many different ways to code a for loop in JavaScript, but not all of them are as efficient as a benchmark of Greg Reimer pointed out. This benchmark was done back in 2008 and the browsers have evolved a long way in this time, so it's time to see what's what.

Lets fist see what loops there are:
Basic for loop.
for (var i=0; i<arr.length; i++) {}
For loop, but caching the length.
for (var i=0, len=arr.length; i<len; i++) {}
While loop that imitates a for loop.
var i = 0;
while (i<arr.length) {
    i++;
}
While loop that imitates a for loop, caching the length.
var i=0, len=arr.length;
while (i<len) {
    i++;
}
While loop in reverse, simplifying the test condition.
var i = arr.length; while (i--) {}
While looping by popping values (this fails on sparse arrays).
var x;
while (x = arr.pop()) {} 
For loop, testing on existence rather than length (this fails on sparse arrays).
for (var i=0; arr[i]; i++) {}
For loop, testing on existence rather than length, plus array lookup.
for (var i=0; arr[i]; i++) {
    var x = arr[i];
}
For loop, testing on existence rather than length, array lookup is combined with test.
for (var i=0, x; x = arr[i++];) {}
For reference.
for (var i=0, len=arr.length; i<len; i++) {
    var x = arr[i];
}
Array.forEach() native implementation.
arr.forEach(function(x){});
Angular.forEach() native implementation.
angular.forEach(arr, function(x){});
jQuery.forEach() native implementation.
jQuery.each(arr, function(i,val){});

Test systems

Android Chrome version 18.0.1025469 on android 4.2.1 Nexus 7
IOS Safari 8536.25 on IOS 6.1 Ipad v4
Chrome Chrome version 24.0.1312.57 on Mac OSX
Safari Safari version 6.0.2 (8536.26.17) on Mac OSX
Firefox Firefox version 18.0.2 on Mac OSX
IE10 Internet Explorer 10.0.9200.16466 on Windows 8 RT
Used Angular 1.0.3 and jQuery 1.9.0 for the for each loops.

Results

I normalized the results so instead of showing the times i will show the percentage. 100% is the fastest time and for example 123 is 23% slower than the fastest time.
Legend
100%
101% – 115%
> 300%
Modern browsers optimize some code blocks to the point of skipping them all together. First I tested the arrays with a simple calculation inside (adding the number in the array to a result variable). And once with just the array loops.

Testing while using the array


Android IOS Chome Safari Firefox IE10
Basic for loop 112 131 139 121 123 174
For loop, but caching the length 100 103 100 100 112 113
While loop that imitates a for loop 100 124 139 119 119 169
While loop that imitates a for loop, caching the length 101 102 109 101 107 136
While loop in reverse, simplifying the test condition 177 100 107 101 100 181
While looping by popping values 363 131 223 133 131 618
For loop, testing on existence rather than length 127 135 227 130 136 180
For loop, testing on existence rather than length, array lookup combined 134 102 118 104 120 100
For reference 101 103 111 105 120 146
Array.forEach() native implementation 607 449 2461 299 963 421
Angular.forEach() implementation 570 447 2377 296 985 365
jQuery.forEach() implementation 2859 614 3930 366 669 1181

Just the loops


Android IOS Chome Safari Firefox IE10
Basic for loop 100 279 106 103 100 163
For loop, but caching the length 101 130 100 114 106 108
While loop that imitates a for loop 152 279 100 100 106 146
While loop that imitates a for loop, caching the length 102 121 100 114 106 100
While loop in reverse, simplifying the test condition 116 100 133 111 135 165
While looping by popping values 1600 525 461 216 924 2250


The following tests where optimized by all browsers to a point that they can't be measured or skipped:

For loop, testing on existence rather than length (this fails on sparse arrays)
For loop, testing on existence rather than length, array lookup is combined with test
For reference
Array.forEach() native implementation
Angular.forEach() implementation
jQuery.forEach() implementation

Conclusion

Even with the modern browser its still important to use a correct loop while iterating over a large array.
The 'For loop, but caching the length' (for (var i=0, len=arr.length; i<len; i++) {}) is the best option for now its the one of the fastest on every test expect the IOS test with just the loops. And is safe to say that it is advised to stay away from the for each loops. As they are usually more than 3 times as slow sometime up to 28 times as slow in the case on android with jQuery.

You can download the sources of the test from my GitHub account: https://github.com/Japio007/2013-02-JS-PerformaceTest

No comments:

Post a Comment