Object Instantiation Benchmark

JavaScript performance comparison

Revision 2 of this test case created by Aadit M Shah

Info

After seeing JavaScript class libraries like JSFace, my.Class and OxygenJS run super fast on Firefox I wanted to see what makes them so fast.

I have a nagging feeling that they break the instanceof operator which is why they are so fast. It's kind of like cheating the end user, so I want to expose the flaws I discover. I'll be using my own javascript/augment library as the control.

Preparation code

<script src="http://dl.dropbox.com/u/7677927/oop-benchmark/lib/jsface.js"></script>
<script src="http://dl.dropbox.com/u/7677927/oop-benchmark/lib/my.class.js"></script>
<script src="https://raw.github.com/javascript/augment/master/augment.js"></script>
<script src="https://raw.github.com/torworx/oxygen/master/oxygen.js"></script>
<script src="http://indigounited.com/dejavu/dejavu.js"></script>
<script>
  var JSFacePerson = jsface.Class({
    constructor: function(name) {
      this.name = name;
    },
    setAddress: function(country, city, street) {
      this.country = country;
      this.city = city;
      this.street = street;
    }
  });

  var JSFaceFrenchGuy = jsface.Class(JSFacePerson, {
    constructor: function(name) {
      JSFaceFrenchGuy.$super.call(this, name);
    },
    setAddress: function(city, street) {
      JSFaceFrenchGuy.$superp.setAddress.call(this, 'France', city, street);
    }
  });

  var JSFaceParisLover = jsface.Class(JSFaceFrenchGuy, {
    constructor: function(name) {
      JSFaceParisLover.$super.call(this, name);
    },
    setAddress: function(street) {
      JSFaceParisLover.$superp.setAddress.call(this, 'Paris', street);
    }
  });

  var MyPerson = my.Class({
    constructor: function(name) {
      this.name = name;
    },
    setAddress: function(country, city, street) {
      this.country = country;
      this.city = city;
      this.street = street;
    }
  });

  var MyFrenchGuy = my.Class(MyPerson, {
    constructor: function(name) {
      MyFrenchGuy.Super.call(this, name);
    },
    setAddress: function(city, street) {
      MyFrenchGuy.Super.prototype.setAddress.call(this, 'France', city, street);
    }
  });

  var MyParisLover = my.Class(MyFrenchGuy, {
    constructor: function(name) {
      MyParisLover.Super.call(this, name);
    },
    setAddress: function(street) {
      MyParisLover.Super.prototype.setAddress.call(this, 'Paris', street);
    }
  });

  var dejavuClassPerson3 = dejavu.Class.declare(function () {
    return {
          initialize: function(name){
              this.name = name;
          },
          setAddress: function(country, city, street) {
              this.country = country;
              this.city = city;
              this.street = street;
          }
      };
  }, true);

  var dejavuClassFrenchGuy3 = dejavuClassPerson3.extend(function ($super) {
     return {
         setAddress: function(city, street) {
             $super.setAddress.call(this, 'France', city, street);
         }
     };
  }, true);

  var dejavuClassParisLover3 = dejavuClassFrenchGuy3.extend(function ($super) {
      return {
          setAddress: function(street) {
              $super.setAddress.call(this, 'Paris', street);
          }
      };
  }, true);

  // OxygenJS Define
  var OxyPerson = Oxy.define({
    constructor: function(name) {
      this.name = name;
    },
    setAddress: function(country, city, street) {
      this.country = country;
      this.city = city;
      this.street = street;
    }
  });

  var OxyChinaGuy = Oxy.define({
    extend: OxyPerson,
    constructor: function(name) {
      OxyChinaGuy.$superclass.call(this, name)
    },
    setAddress: function(city, street) {
      OxyChinaGuy.$super.setAddress.call(this, 'China', city, street);
    }
  });

  var OxyBeijingLover = Oxy.define({
    extend: OxyChinaGuy,
    constructor: function(name) {
      OxyBeijingLover.$superclass.call(this, name);
    },
    setAddress: function(street) {
      OxyBeijingLover.$super.setAddress.call(this, 'Beijing', street);
    }
  });


  var AugmentPerson = Object.augment(function() {
    this.setAddress = function(country, city, street) {
      this.country = country;
      this.city = city;
      this.street = street;
    };

    return AugmentPerson;

    function AugmentPerson(name) {
      this.name = name;
    }
  });

  var AugmentFrenchGuy = AugmentPerson.augment(function(AugmentPerson, uber) {
    var setAddress = uber.setAddress;

    this.setAddress = function(city, street) {
      setAddress.call(this, "France", city, street);
    };

    return AugmentFrenchGuy;

    function AugmentFrenchGuy(name) {
      AugmentPerson.call(this, name);
    }
  });

  var AugmentParisLover = AugmentFrenchGuy.augment(function(AugmentFrenchGuy, uber) {
    var setAddress = uber.setAddress;

    this.setAddress = function(street) {
      setAddress.call(this, "Paris", street);
    };

    return AugmentParisLover;

    function AugmentParisLover(name) {
      AugmentFrenchGuy.call(this, name);
    }
  });
</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
JSFace
var mary = new JSFaceParisLover("Mary");

var instance = mary instanceof JSFaceParisLover &&
               mary instanceof JSFaceFrenchGuy &&
               mary instanceof JSFacePerson;

if (!instance) throw new Error("JSFace failed the `instanceof` test.");
 
pending…
my.Class
var mary = new MyParisLover("Mary");

var instance = mary instanceof MyParisLover &&
               mary instanceof MyFrenchGuy &&
               mary instanceof MyPerson;

if (!instance) throw new Error("my.Class failed the `instanceof` test.");
pending…
augment
var mary = new AugmentParisLover("Mary");

var instance = mary instanceof AugmentParisLover &&
               mary instanceof AugmentFrenchGuy &&
               mary instanceof AugmentPerson;

if (!instance) throw new Error("augment failed the `instanceof` test.");
pending…
OxygenJS
var mary = new OxyBeijingLover("Mary");

var instance = mary instanceof OxyBeijingLover &&
               mary instanceof OxyChinaGuy &&
               mary instanceof OxyPerson;

if (!instance) throw new Error("OxygenJS failed the `instanceof` test.");
pending…
dejavu optimized closures
var mary = new dejavuClassParisLover3("Mary");

var instance = mary instanceof dejavuClassParisLover3 &&
               mary instanceof dejavuClassFrenchGuy3 &&
               mary instanceof dejavuClassPerson3;

if (!instance) throw new Error("dejavu optimized closures failed the `instanceof` test.");
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