Trey Keown
Trey Keown

Reputation: 1355

Exceptionally slow Javascript loop

This is, in a way, a follow-up to my previous question.

I created a jsPerf which compares a number of ways to take a 1-dimensional array of RGB pixel values

var rgb = [R, G, B, R, G, B...]

And convert those into RGBA values for an HTML5 canvas (where the alpha channel is always 255, fully opaque).

var rgba = [R, G, B, 255, R, G, B, 255...]

In my tests, I found that one of the loops I tested, titled "For Loop", is astronomically slower than the other loops. Where other loops were completing the operation hundreds of millions of times per second, it weighed in at a whopping 86 times per second. The loop can be found in the jsPerf link above, but here's a bit of code with "For Loop" and "4*unrolled, skip alpha", one of the faster loops in the test.

//Setup for each test
function newFilledArray(length, val) {
    var array = Array(length);
    for (var i = 0; i < length; i++) {
        array[i] = val;
    }
    return array;
}

var w = 160;  //width
var h = 144;  //height

var n = 4 * w * h; //number of length of RGBA arrays
var s = 0, d = 0;  //s is the source array index, d is the destination array index

var rgba_filled = newFilledArray(w*h*4, 255);  //an RGBA array to be written to a canvas, prefilled with 255's (so writing to the alpha channel can be skipped
var rgb = newFilledArray(w*h*3, 128);  //our source RGB array (from an emulator's internal framebuffer)

//4*unrolled, skip alpha - loop completes (exits) 185,693,068 times per second
while (d < n) {
    rgba_filled[d++] = rgb[s++];
    rgba_filled[d++] = rgb[s++];
    rgba_filled[d++] = rgb[s++];
    d++;
}

//For Loop - loop completes (exits) 85.87 times per second
for (var d = 0; d < n; ++d) {
    rgba_filled[d++] = rgb[s++];
    rgba_filled[d++] = rgb[s++];
    rgba_filled[d++] = rgb[s++];
}

How can it be so incredibly similar in syntax, yet is so far removed in terms of performance?

Upvotes: 7

Views: 1997

Answers (1)

Ja͢ck
Ja͢ck

Reputation: 173652

The reason why only the for loop is so slow is because it's the only correct test case; all the other test cases never reset, amongst others, the value of d, so the first iteration is normal and the rest is obviously super fast :)

This jsperf gives a better outcome, whereby the for-loop is only slightly slower than the fastest result.

Update

As bfavaretto suggested, you should also reset s and the target array that you're building for a more consistent result. His results can be found here.

Upvotes: 10

Related Questions