Programming on a Jerker PART 5: Classless Versus Prototype Speed Test or: How I learned that benchtesting javascript is difficult

Warning: this is a post entirely for those Jerkers, I mean “Jerks”, who program JavaScript at their Ikea desks.

Well colour me surprised; sorry about the exceptional Canadian spelling. I expected to see negligible execution time differences when comparing similar classless and prototypal JavaScript programs with each other. Both test programs have a child function call a parent function 10,000,000 times. I ran the classless and the prototypal in Chrome and Firefox ten times each in the console. Yes, unscientific, but good enough for me. The numbers below are in milliseconds.

26840 31984 31291 30123 31636 30487 38455 37558 40240 38358
Chrome Functional average: 33697
22399 23928 26580 22713 23162 20189 26737 25834 20698 20698 
Firefox Functional average: 23294
27807 28048 27414 27326 27693 31926 29182 39366 33540 34279
Chrome Prototypal average: 30658
30936 29869 28678 28187 30045 38294 32238 26926 25878 26271
Firefox Prototypal average: 29732

As you can see, Firefox was faster in both cases. The surprising fact is that the classless type was faster in Firefox, slower in Chrome. But overall, there wasn’t much difference, especially when you consider, there were 20,000,000 function calls. I consider prototypal and classless JavaScript to have about the same speeds.

I hear you say: “But all that copying has to use more memory in the classless version, Steen.”

To this, I say to you: “yep you are right. But this is because Crockford’s classless style require objects have their own copy of duplicate code in many instances, more memory is used.”

It bears repeating, “my cheap android phone has 12gb”, memory just does not matter anymore.

Here is the classless “Functional” program:

clear();
function privitizeNewVariables(specs) {
    if (!specs.is_private) {
        var members = Object.assign({}, specs);
        members.is_private = true;
        return members;
    }
    return specs;
}
function newFunctionalLevel1(specs) {
    var members = privitizeNewVariables(specs);
    functionalWasteTime = function (i) {
  //      console.log('in functionalLevel1', i)
        return i;
    };
    return Object.freeze({
        functionalWasteTime: functionalWasteTime
    });
}
function newFunctionalLevel2(specs) {
    var members = privitizeNewVariables(specs);
    var an_animal = newFunctionalLevel1(members);
    functionalWasteTime = function (i) {
    //    console.log('in functionalLevel2', i)
        return an_animal.functionalWasteTime(i);
    };
    return Object.freeze({
        functionalWasteTime: functionalWasteTime
    });
}
var functional_obj = newFunctionalLevel2({});
var loops =10000000;
var start = +new Date();
var functional_accum = 0;
for (var j = loops; j > 0; j--) {
  functional_accum += functional_obj.functionalWasteTime(j);
}
var end = +new Date();
var diff = end - start;
console.log('functional', diff);

Here is the this and new using “Prototypal” program, I must say it is a lot shorter:

clear();
var prototypeLevel1 = function () {};
prototypeLevel1.prototype.functionalWasteTime = function (i) {
   // console.log('in prototypeLevel1', i)
    return i;};
var prototypeLevel2 = function () { };
prototypeLevel2.prototype = Object.create(prototypeLevel1.prototype);
prototypeLevel2.prototype.constructor = prototypeLevel2;
prototypeLevel2.prototype.functionalWasteTime = function (i) {
    //console.log('in prototypeLevel2', i)
    prototypeLevel1.prototype.functionalWasteTime(i);};
var prototype_obj = new prototypeLevel2();

var loops =10000000;
var start = +new Date();
var functional_accum = 0;
for (var j = loops; j > 0; j--) {
    functional_accum += prototype_obj.functionalWasteTime(j);
}
var end = +new Date();
var diff = end - start;
console.log('prototypal', diff);

Part  1  2  3  4  5  6  7

Leave a Reply

Your email address will not be published.