Object VS Array

JavaScript performance comparison

Revision 17 of this test case created

Info

More details at my blog : http://pic-o.com/blog/2011/11/native-linked-list-hack-vs-array

Obj VS Arr

Javascript lacked native linkedlist support, and for an interpretive language, rebuilding the engine, is a costly alternative, marginalizing the benefits.

Or so we thought... hidden within the DOM specification, are linked lists. The ability to rapidly manipulate nested children of DOM structures in the modern browsers, is in part attributed to linked lists. Hence why not exploit it for data instead of dom objects. or perhaps both?

Test Notes

  1. All tests runs atleast an int++ / -- operation, for consistency between the various tests. [hence its faster then its reported]
  2. Setup calls are not timed;
  3. populate sets the limit / range for pre-filled content test
  4. As much as possible, we try to ensure equal, variable calls / read / writes in similar test. To provide more consistent reasults
  5. A random sample of the test is intentionally leaked to global testDump variable space, to prevent JIT optimization.

Preparation code

 
<script>
Benchmark.prototype.setup = function() {
    //Base variable creation testing
    var read;
   
    var zero = 0;
    var blankObj = {};
    var blankArr = [];
   
    //Population limit for pre generated content
    var populateLimit = 1000;
    var populateMid = populateLimit / 2;
    var populateNext = populateLimit + 1;
   
    var count = 0;
    var countMid = populateMid;
    var countNext = populateNext;
   
    var objPopLimit = 'p' + populateLimit;
    var objPopMid = 'p' + populateMid;
    var objPopNext = 'p' + populateNext;
    var objPopZero = 'p' + zero;
   
    //Premade content testing
    var testObj = {};
    for (var a = 0; a <= populateLimit; a++) {
      testObj['p' + a] = a;
    }
    var testArr = [];
    for (var a = 0; a <= populateLimit; a++) {
      testArr[a] = ('p' + a);
    }
   
};

Benchmark.prototype.teardown = function() {
    if( !window.testDump ) {
    window.testDump = [];
    }
   
    if( Math.random() >= 0.9999 ) {
    window.testDump.push( [
        blankObj['p'+Math.round(Math.random()*1000)],
        (blankArr.length > 0)?( blankArr[ Math.round(Math.random()*( blankArr.length-1 )) ] ) : 0,
        testObj['p'+Math.round(Math.random()*1000)],
        (testArr.length > 0)?( testArr[ Math.round(Math.random()*( testArr.length-1 )) ] ) : 0
    ] );
    }
};
</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
Obj Creates
read = {};
count++;
pending…
Obj (blank) Property Adds
blankObj['p' + count] = count;
count++;
pending…
Obj (filled) Property Adds
testObj['p' + countNext] = countNext;
countNext++;
pending…
Obj Delete Starts
delete testObj['p' + count];
count++;
pending…
Obj Null Starts
testObj['p' + count] = null;
count++;
pending…
Obj Delete Mids
delete testObj['p' + countMid];
countMid++;
pending…
Obj Null Mids
testObj['p' + countMid] = null;
countMid++;
pending…
Obj Delete Ends
countNext--;
delete testObj['p' + countNext];
pending…
Obj Null Ends
countNext--;
testObj['p' + countNext] = null;
pending…
Obj Read start
read = testObj[objPopZero];
count++;
pending…
Obj Read Mid
read = testObj[objPopMid];
count++;
pending…
Obj Read End
read = testObj[objPopLimit];
count++;
pending…
Obj Write Start
testObj[objPopZero] = count;
count++;
pending…
Obj Write Mid
testObj[objPopMid] = count;
count++;
pending…
Obj Write End
testObj[objPopLimit] = count;
count++;
pending…
Array Create
read = [];
count++;
pending…
Array (blank) Property Add
blankArr[count] = ('p' + count);
count++;
pending…
Array (filled) Property Add
testArr[countNext] = ('p' + countNext);
countNext++;
pending…
Array (blank) .push
blankArr.push(count);
count++;
pending…
Array (filled) .push
testArr.push(count);
count++;
pending…
Array (filled) .pop
testArr.pop();
count++;
pending…
Array (filled) .shift
testArr.shift();
count++;
pending…
Array (filled) .unshift
testArr.unshift(count);
count++;
pending…
Array (blank) .unshift
testArr.unshift(count);
count++;
pending…
Array (filled) .slice(start, mid)
read = testArr.slice(zero, populateMid);
count++;
pending…
Array (filled) .slice(mid, [end])
read = testArr.slice(populateMid);
count++;
pending…
Array (filled) .slice(mid, end)
read = testArr.slice(populateMid, populateNext);
count++;
pending…
Array (filled) .slice(mid, end)
read = testArr.slice(populateMid, populateLimit);
count++;
pending…
Array Delete Start
delete testArr[count];
count++;
pending…
Array Null Start
testArr[count] = null;
count++;
pending…
Array Delete Mid
delete testArr[countMid];
countMid++;
pending…
Array Null Mid
testArr[countMid] = null;
countMid++;
pending…
Array Delete End
countNext--;
delete testArr[countNext];
pending…
Array Null End
countNext--;
testArr[countNext] = null;
pending…
Array Read Start
read = testArr[zero];
count++;
pending…
Array Read Mid
read = testArr[populateMid];
count++;
pending…
Array Read End
read = testArr[populateLimit];
count++;
pending…
Array Write Start
testArr[zero] = count;
count++;
pending…
Array Write Mid
testArr[populateMid] = count;
count++;
pending…
Array Write End
testArr[populateLimit] = count;
count++;
pending…
Array Splice Mid Insert
testArr.splice(populateMid, 0, count);
count++;
pending…
Array Splice Mid Remove
//I have no idea how to fix this, to prevent out of bound
testArr.splice(populateMid, 1);
count++;
pending…
Array splice removal
//I have no idea how to fix this, to prevent out of bound
testArr.splice(populateMid, 1);
count++;
pending…
Array splice removal add
//I have no idea how to fix this, to prevent out of bound
testArr.splice(populateMid, 1, count);
count++;
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