Typed Array vs JS Array using Memory Scratchpad

JavaScript performance comparison

Test case created by Corey Clark

Info

Testing calculation speed of Typed Array vs standard JS Arrays using a Reusable Memory scratchpad. Want to test performance of Vector math using Typed vs JS arrays for physics engine, but do not want to recreate arrays for each call, rather using a shared memory scratch pad for all calculations. The scratch pad needs to be a circular linked list so next available array can be used and loop back to beginning once last array is used.

Preparation code

 
<script>
Benchmark.prototype.setup = function() {
    var CMap = function(linkEntries){
        this.current = undefined;
        this.size = 0;
        this.isLinked = true;                  
    };
    CMap.prototype.hash = function(value){
        return value instanceof Object ? (value.__hash ||
                (value.__hash = 'object ' + ++arguments.callee.current)) :
                (typeof value) + ' ' + String(value);
    };
    CMap.prototype.hash.current = 0;            
    CMap.prototype.link = function(entry){
            if(this.size === 0) {
                    entry.prev = entry;
                    entry.next = entry;
                    this.current = entry;
            }
            else {
                    entry.prev = this.current.prev;
                    entry.prev.next = entry;
                    entry.next = this.current;
                    this.current.prev = entry;
            }
    };
    CMap.prototype.unlink = function(entry) {
            if(this.size === 0)
                    this.current = undefined;
            else {
                    entry.prev.next = entry.next;
                    entry.next.prev = entry.prev;
                    if(entry === this.current)
                            this.current = entry.next;
            }
    };
    CMap.prototype.get = function(key) {
            var entry = this[this.hash(key)];
            return typeof entry === 'undefined' ? undefined : entry.value;
    };
    CMap.prototype.put = function(key, value) {
            var hash = this.hash(key);
   
            if(this.hasOwnProperty(hash))
                    this[hash].value = value;
            else {
                    var entry = { key : key, value : value };
                    this[hash] = entry;
   
                    this.link(entry);
                    ++this.size;
            }
   
            return this;
    };
    CMap.prototype.next = function() {
            this.current = this.current.next;
    };
    CMap.prototype.value = function() {
            return this.current.value;
    };
   
   
    var TypeArrayList = new CMap();
    var JSArrayList = new CMap();
   
    TypeArrayList.put(0,new Float32Array([1.0,2.0,3.0,1.0,2.0,3.0,1.0,2.0,3.0,1.0,2.0,3.0]));
    TypeArrayList.put(1,new Float32Array([1.0,2.0,3.0,1.0,2.0,3.0,1.0,2.0,3.0,1.0,2.0,3.0]));
    TypeArrayList.put(2,new Float32Array([1.0,2.0,3.0,1.0,2.0,3.0,1.0,2.0,3.0,1.0,2.0,3.0]));
    TypeArrayList.put(3,new Float32Array([1.0,2.0,3.0,1.0,2.0,3.0,1.0,2.0,3.0,1.0,2.0,3.0]));
   
    JSArrayList.put(0, [1.0,2.0,3.0,1.0,2.0,3.0,1.0,2.0,3.0,1.0,2.0,3.0]);
    JSArrayList.put(1, [1.0,2.0,3.0,1.0,2.0,3.0,1.0,2.0,3.0,1.0,2.0,3.0]);
    JSArrayList.put(2, [1.0,2.0,3.0,1.0,2.0,3.0,1.0,2.0,3.0,1.0,2.0,3.0]);
    JSArrayList.put(3, [1.0,2.0,3.0,1.0,2.0,3.0,1.0,2.0,3.0,1.0,2.0,3.0]);
   
   
    var input1 = [1.0,2.0,3.0,1.0,2.0,3.0,1.0,2.0,3.0,1.0,2.0,3.0];
    var input2 = [4.0,5.0,6.0,4.0,5.0,6.0,4.0,5.0,6.0,4.0,5.0,6.0];
   
    var typeArray1 = new Float32Array([1.0,2.0,3.0,1.0,2.0,3.0,1.0,2.0,3.0,1.0,2.0,3.0]);
   
    var typeArray2 = new Float32Array([1.0,2.0,3.0,1.0,2.0,3.0,1.0,2.0,3.0,1.0,2.0,3.0]);
   
    var dot = function(v1, v2, out){
           
        return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
       
    }
    var cross = function(vec,vec2,dest){
       
        var x = vec[0], y = vec[1], z = vec[2];
        var x2 = vec2[0], y2 = vec2[1], z2 = vec2[2];
       
        dest[0] = y*z2 - z*y2;
        dest[1] = z*x2 - x*z2;
        dest[2] = x*y2 - y*x2;
    }
   
    var matMultiplyCached = function(mat, mat2, dest){
        if(!dest) { dest = mat }
       
        // Cache the matrix values (makes for huge speed increases!)
        var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3];
        var a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7];
        var a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11];
        var a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15];
       
        var b00 = mat2[0], b01 = mat2[1], b02 = mat2[2], b03 = mat2[3];
        var b10 = mat2[4], b11 = mat2[5], b12 = mat2[6], b13 = mat2[7];
        var b20 = mat2[8], b21 = mat2[9], b22 = mat2[10], b23 = mat2[11];
        var b30 = mat2[12], b31 = mat2[13], b32 = mat2[14], b33 = mat2[15];
       
        dest[0] = b00*a00 + b01*a10 + b02*a20 + b03*a30;
        dest[1] = b00*a01 + b01*a11 + b02*a21 + b03*a31;
        dest[2] = b00*a02 + b01*a12 + b02*a22 + b03*a32;
        dest[3] = b00*a03 + b01*a13 + b02*a23 + b03*a33;
        dest[4] = b10*a00 + b11*a10 + b12*a20 + b13*a30;
        dest[5] = b10*a01 + b11*a11 + b12*a21 + b13*a31;
        dest[6] = b10*a02 + b11*a12 + b12*a22 + b13*a32;
        dest[7] = b10*a03 + b11*a13 + b12*a23 + b13*a33;
        dest[8] = b20*a00 + b21*a10 + b22*a20 + b23*a30;
        dest[9] = b20*a01 + b21*a11 + b22*a21 + b23*a31;
        dest[10] = b20*a02 + b21*a12 + b22*a22 + b23*a32;
        dest[11] = b20*a03 + b21*a13 + b22*a23 + b23*a33;
        dest[12] = b30*a00 + b31*a10 + b32*a20 + b33*a30;
        dest[13] = b30*a01 + b31*a11 + b32*a21 + b33*a31;
        dest[14] = b30*a02 + b31*a12 + b32*a22 + b33*a32;
        dest[15] = b30*a03 + b31*a13 + b32*a23 + b33*a33;
    }
   
    var matMultiply = function(mat, mat2, dest){
        if(!dest) { dest = mat }
   
        dest[0] = mat2[0]*mat[0] + mat2[1]*mat[4] + mat2[2]*mat[8] + mat2[3]*mat[12];
        dest[1] = mat2[0]*mat[1] + mat2[1]*mat[5] + mat2[2]*mat[9] + mat2[3]*mat[13];
        dest[2] = mat2[0]*mat[2] + mat2[1]*mat[6] + mat2[2]*mat[10] + mat2[3]*mat[14];
        dest[3] = mat2[0]*mat[3] + mat2[1]*mat[7] + mat2[2]*mat[11] + mat2[3]*mat[15];
        dest[4] = mat2[4]*mat[0] + mat2[5]*mat[4] + mat2[6]*mat[8] + mat2[7]*mat[12];
        dest[5] = mat2[4]*mat[1] + mat2[5]*mat[5] + mat2[6]*mat[9] + mat2[7]*mat[13];
        dest[6] = mat2[4]*mat[2] + mat2[5]*mat[6] + mat2[6]*mat[10] + mat2[7]*mat[14];
        dest[7] = mat2[4]*mat[3] + mat2[5]*mat[7] + mat2[6]*mat[11] + mat2[7]*mat[15];
        dest[8] = mat2[8]*mat[0] + mat2[9]*mat[4] + mat2[10]*mat[8] + mat2[11]*mat[12];
        dest[9] = mat2[8]*mat[1] + mat2[9]*mat[5] + mat2[10]*mat[9] + mat2[11]*mat[13];
        dest[10] = mat2[8]*mat[2] + mat2[9]*mat[6] + mat2[10]*mat[10] + mat2[11]*mat[14];
        dest[11] = mat2[8]*mat[3] + mat2[9]*mat[7] + mat2[10]*mat[11] + mat2[11]*mat[15];
        dest[12] = mat2[12]*mat[0] + mat2[13]*mat[4] + mat2[14]*mat[8] + mat2[15]*mat[12];
        dest[13] = mat2[12]*mat[1] + mat2[13]*mat[5] + mat2[14]*mat[9] + mat2[15]*mat[13];
        dest[14] = mat2[12]*mat[2] + mat2[13]*mat[6] + mat2[14]*mat[10] + mat2[15]*mat[14];
        dest[15] = mat2[12]*mat[3] + mat2[13]*mat[7] + mat2[14]*mat[11] + mat2[15]*mat[15];
    }
};
</script>

Test runner

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

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
Preloaded Typed Array Cached
TypeArrayList.next();
var v1  = TypeArrayList.value();

TypeArrayList.next();
var v2 = TypeArrayList.value();

matMultiplyCached(v1,v2);
pending…
Preloaded JS Array Cached
JSArrayList.next();
var v1  = JSArrayList.value();

JSArrayList.next();
var v2 = JSArrayList.value();

matMultiplyCached(v1,v2);
pending…
Preloaded Typed Array
TypeArrayList.next();
var v1  = TypeArrayList.value();

TypeArrayList.next();
var v2 = TypeArrayList.value();

matMultiply(v1,v2);
pending…
Preloaded JS Array
JSArrayList.next();
var v1  = JSArrayList.value();

JSArrayList.next();
var v2 = JSArrayList.value();

matMultiply(v1,v2);
pending…
Preloaded TypeArray - Non Scratchpad
matMultiplyCached(typeArray1, typeArray2);
pending…
Preloaded JS Array - Non Scratchpad
matMultiplyCached(input1, input2);
pending…

You can edit these tests or add even more tests to this page by appending /edit to the URL.

Compare results of other browsers

0 comments

Add a comment