7

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?

5
  • have you tried switching the order of the loops Commented Jul 9, 2013 at 3:29
  • Did you try using dis()? Commented Jul 9, 2013 at 3:30
  • 1
    @aaronman What do you mean? jsperf runs each test in a fresh JS environment. Commented Jul 9, 2013 at 3:30
  • didn't even read the question just looked at the code, my bad @Barmar Commented Jul 9, 2013 at 3:32
  • 1
    The first indicator that something's not quite right with those benchmarks is that if the entire while loop were really running that many times per second, that would mean it was carrying out about 290 trillion operations per second! That would have to be one heck of a browser/CPU combo. So it's not that the for loop is exceptionally slow (it's not; it's carrying out about 134 million operations per second), but rather that the while loop was showing as absurdly fast. Commented Jul 9, 2013 at 5:10

1 Answer 1

10

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.

Sign up to request clarification or add additional context in comments.

9 Comments

I think he was assuming that the prep code was re-run before each iteration of the test.
@Barmar That would be my guess as well :)
Good catch! What confused me is that setup states that it "runs before each clocked test loop, outside of the timed code region". That wording still maked it sound like setup should operate as I thought it would!
@TreyKeown If you also reset s and the target array, you get a lot more ops/sec (and a more consistent end state) on all tests. jsperf.com/rgb-to-rgba/9
@bfavaretto thanks! I took your revision and updated it so that everything is, truly, getting reset. What is hopefully the final revision of this test can be found here: jsperf.com/rgb-to-rgba/11
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.