asm.js rng

JavaScript performance comparison

Revision 4 of this test case created by Tomi Aarnio

Info

Compare different implementations of the same routine (random number generation).

Preparation code

<script>
function RNGModule1(stdlib, foreign, heap) {
  "use asm"

  var ITER = 15;
  var k0 = 0xA341316C;
  var k1 = 0xC8013EA4;
  var k2 = 0xAD90777D;
  var k3 = 0x7E95761E;
  var delta = 0x9E3779B9;
  var dst = new stdlib.Uint8Array(heap);
  var i = 0,
    j = 0,
    k = 0,
    x = 0,
    y = 0,
    r = 0,
    sum = 0;

  function rng(worksize, seed, iter) {
    worksize = worksize | 0;
    seed = seed | 0;
    iter = iter | 0;
    ITER = ITER | 0;
    k0 = k0 | 0;
    k1 = k1 | 0
    k2 = k2 | 0
    k3 = k3 | 0
    delta = delta | 0;
    for (k = 0; (k | 0) < (iter | 0); k = (k + 1) | 0) {
      for (i = 0; (i | 0) < (worksize | 0); i = (i + 1) | 0) {
        x = seed;
        y = x << 3;
        x = ((x|0) + ((i + (((i << 11) + (i << 19))|0))|0)) | 0;
        y = ((y|0) + ((i + (((i << 9) + (i << 21))|0))|0))| 0;
        sum = 0;
        for (j = 0; (j | 0) < (ITER | 0); j = (j + 1) | 0) {
          sum = (sum + delta) | 0;
          x = ((x|0) + (((y << 4) + k0) & (y + sum) & (((y >>> 5) + k1))))|0;
          y = ((y|0) + (((x << 4) + k2) & (x + sum) & (((x >>> 5) + k3))))|0;
        }
        r = (x & 0x00ff);
        dst[i] = r;
      }
    }
  };

  return rng;
}

function RNGModule2(stdlib, foreign, heap) {
  var ITER = 15;
  var k0 = 0xA341316C;
  var k1 = 0xC8013EA4;
  var k2 = 0xAD90777D;
  var k3 = 0x7E95761E;
  var delta = 0x9E3779B9;
  var dst = new stdlib.Uint8Array(heap);
  var i = 0,
    j = 0,
    k = 0,
    x = 0,
    y = 0,
    r = 0,
    sum = 0;

  function rng(worksize, seed, iter) {
    worksize = worksize | 0;
    seed = seed | 0;
    iter = iter | 0;
    ITER = ITER | 0;
    k0 = k0 | 0;
    k1 = k1 | 0
    k2 = k2 | 0
    k3 = k3 | 0
    delta = delta | 0;
    for (k = 0; (k | 0) < (iter | 0); k = (k + 1) | 0) {
      for (i = 0; (i | 0) < (worksize | 0); i = (i + 1) | 0) {
        x = seed;
        y = x << 3;
        x = ((x|0) + ((i + (((i << 11) + (i << 19))|0))|0)) | 0;
        y = ((y|0) + ((i + (((i << 9) + (i << 21))|0))|0))| 0;
        sum = 0;
        for (j = 0; (j | 0) < (ITER | 0); j = (j + 1) | 0) {
          sum = (sum + delta) | 0;
          x = ((x|0) + (((y << 4) + k0) & (y + sum) & (((y >>> 5) + k1))))|0;
          y = ((y|0) + (((x << 4) + k2) & (x + sum) & (((x >>> 5) + k3))))|0;
        }
        r = (x & 0x00ff);
        dst[i] = r;
      }
    }
  };

  return rng;
}

function RNGModule3(stdlib, foreign, heap) {
  var dst = new stdlib.Uint8Array(heap);

  function rng(worksize, seed, iter) {
    var ITER = 15;
    var k0 = 0xA341316C | 0;
    var k1 = 0xC8013EA4 | 0;
    var k2 = 0xAD90777D | 0;
    var k3 = 0x7E95761E | 0;
    var delta = 0x9E3779B9 | 0;
    var seed = seed | 0;

    for (var k = 0; k < iter; k++) {
      for (var i = 0; i < worksize; i++) {
        var x = seed;
        var y = x << 3;
        x = (x + ((i + (((i << 11) + (i << 19))|0))|0)) | 0;
        y = (y + ((i + (((i << 9) + (i << 21))|0))|0))| 0;
        var sum = 0;
        for (var j = 0; j < ITER; j++) {
          sum = (sum + delta) | 0;
          x = (x + (((y << 4) + k0) & (y + sum) & (((y >>> 5) + k1)))) | 0;
          y = (y + (((x << 4) + k2) & (x + sum) & (((x >>> 5) + k3)))) | 0;
        }
        var r = (x & 0x00ff);
        dst[i] = r;
      }
    }
  };

  return rng;
}

function RNGModule4(stdlib, foreign, heap) {
  var dst = new stdlib.Uint8Array(heap);

  function rng(worksize, seed, iter) {
    var ITER = 15;
    var k0 = 0xA341316C;
    var k1 = 0xC8013EA4;
    var k2 = 0xAD90777D;
    var k3 = 0x7E95761E;
    var delta = 0x9E3779B9;

    for (var k = 0; k < iter; k++) {
      for (var i = 0; i < worksize; i++) {
        var x = seed;
        var y = x << 3;
        x += i + (i << 11) + (i << 19);
        y += i + (i << 9) + (i << 21);
        var sum = 0;
        for (var j = 0; j < ITER; j++) {
          sum += delta;
          x += ((y << 4) + k0) & (y + sum) & ((y >>> 5) + k1);
          y += ((x << 4) + k2) & (x + sum) & ((x >>> 5) + k3);
        }
        var r = (x & 0x00ff);
        dst[i] = r;
      }
    }
  };

  return rng;
}


var BUFFERSIZE = 64*1024;
var HEAP1 = new ArrayBuffer(BUFFERSIZE);
var rng1 = RNGModule1(window, null, HEAP1);
var HEAP2 = new ArrayBuffer(BUFFERSIZE);
var rng2 = RNGModule2(window, null, HEAP2);
var HEAP3 = new ArrayBuffer(BUFFERSIZE);
var rng3 = RNGModule3(window, null, HEAP3);
var HEAP4 = new ArrayBuffer(BUFFERSIZE);
var rng4 = RNGModule4(window, null, HEAP4);

rng1(BUFFERSIZE, 0xdeadbeef, 2);
rng2(BUFFERSIZE, 0xdeadbeef, 2);
rng3(BUFFERSIZE, 0xdeadbeef, 2);
rng4(BUFFERSIZE, 0xdeadbeef, 2);
var v1 = new Uint8Array(HEAP1);
var v2 = new Uint8Array(HEAP2);
var v3 = new Uint8Array(HEAP3);
var v4 = new Uint8Array(HEAP4);
for (var i=0; i < BUFFERSIZE; i++) {
  if (v1[i] !== v2[i] ||
      v1[i] !== v3[i] ||
      v1[i] !== v4[i]) {
    throw "Test case outputs not equal to each other."
  }
}
</script>
 

Preparation code output

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
asm.js
rng1(BUFFERSIZE, 0xdeadbeef, 2);
pending…
asm.js w/o "use asm"
rng2(BUFFERSIZE, 0xdeadbeef, 2);

 
pending…
JS w/ asm.js patterns
rng3(BUFFERSIZE, 0xdeadbeef, 2);
pending…
JS w/o asm.js patterns
rng4(BUFFERSIZE, 0xdeadbeef, 2);
pending…

Compare results of other browsers

Revisions

You can edit these tests or add even more tests to this page by appending /edit to the URL. Here’s a list of current revisions for this page:

0 comments

Add a comment