Ripples with asm.js

Surprisingly poor results from asm.js

by Barbos

HTML

<head lang="en">
        <title>Ripple - asm.js test</title>
        <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
        <script type="text/javascript">
            window.onload = function() {
                ripple('myCanvas', 'http://lorempixel.com/600/450/');
            }
        </script>
    </head>
    <body>
        <button id="nonOptimized" disabled>Without asm.js</button>
        <button id="optimized">With asm.js</button>
        <button id="pseudoOptimized">With asm.js (no directive)</button>
        <p>Click on the image below.</p>
        <canvas id="myCanvas" style="border: 1px solid black"></canvas>
        <div id="benchmark"></div>
        <p>This is a test of asm.js optimization, with three cases:</p>
            <ul>
                <li>Running ordinary JavaScript.</li>
                <li>Running valid asm.js JavaScript, with the "use asm" directive included.</li>
                <li>Running valid asm.js JavaScript, with the "use asm" directive omitted.</li>
            </ul>
        <p>RESULTS (as of 8/1/2015):
            <br>Chrome: asm.js runs much slower, especially if the code includes the "use asm"; directive.
            <br>Firefox: asm.js runs slightly slower, and extremely slowly if the code <i>lacks</i> the "use asm"; directive.
            <br>Safari: asm.js runs slightly slower; the "use asm"; directive has no effect.
        </p>
        <div id="console-log"></div>        
    </body>

CSS

.console-line
{
    font-family: monospace;
    margin: 2px;
}

JavaScript

// Version of module not using asm.js
function NonAsmWaveModule(stdlib, foreign, heapBuffer) {

    var w = foreign.width, h = foreign.height, wh = w * h;

    var velocityDampingBitShift = 7, forceDampingBitShift = 2, gammaBitShift = 12;

    var ioImage_offset = 0;
    var masterImage_offset = wh;
    var u0_offset = 2 * wh;
    var u1_offset = 3 * wh;
    var vel_offset = 4 * wh;
    var force_offset = 5 * wh;

    var unsignedHeap = new stdlib.Uint32Array(heapBuffer);
    var signedHeap = new stdlib.Int32Array(heapBuffer);

    function applyCap(x) {
        return x < -0x60000000 ? -0x60000000 : (x > 0x60000000 ? 0x60000000 : x);
    }

    /*
     * Applies the wave equation d2u/dt2 = c*c*(d2u/dx2+d2u/dy2)
     * where all derivatives on the right are partial 2nd derivatives
     */
    function iterate() {

        var index = 0, i = 0, j = 0;

        var uCen = 0, uNorth = 0, uSouth = 0, uEast = 0, uWest = 0;

        var totalCycles = 4;
        for (var cycle = 0; cycle < totalCycles; cycle++) {
            index = 0;
            for (i = 0; i < h; i++) {
                for (j = 0; j < w; j++) {
                    if (i == 0) {
                        index++;
                        continue;
                    }
                    if (i + 1 == h) {
                        index++;
                        continue;
                    }
                    if (j == 0) {
                        index++;
                        continue;
                    }
                    if (j + 1 == w) {
                        index++;
                        continue;
                    }
                    uCen = signedHeap   [u0_offset + index];
                    uNorth = signedHeap[u0_offset + index - w];
                    uSouth = signedHeap[u0_offset + index + w];
                    uWest = signedHeap[u0_offset + index - 1];
                    uEast = signedHeap[u0_offset + index + 1];

                    var uxx = (((uWest + uEast) >> 1) -...