JavaScript Object Oriented Libraries Benchmark

JavaScript performance comparison

Revision 163 of this test case created

Info

Note: JSFace and OxygenJS(fixed and renamed to OvyJS) break the instanceof operator. I wonder what makes my.Class so fast on Firefox. Perhaps the JIT compilation. I would love to see how to leverage that feature.

=== FULL TEST ==

MooTools and Ext Core are removed because they add extra information into native classes. They slow down other libraries.

Ext Core OOP is fast, MooTools OOP is super slow!

TODO: - Add YUI

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="http://dl.dropbox.com/u/7677927/oop-benchmark/lib/jrclass.js">
</script>
<script src="http://dl.dropbox.com/u/7677927/oop-benchmark/lib/klass.js">
</script>
<script src="http://dl.dropbox.com/u/7677927/oop-benchmark/lib/classy.js">
</script>
<script src="http://dl.dropbox.com/u/7677927/oop-benchmark/lib/ptclass.js">
</script>
<script src="https://raw.github.com/javascript/augment/master/augment.js">
</script>
<script src="http://cdn.sencha.com/ext-4.1.1a-gpl/builds/ext-foundation.js">
</script>
<script src="https://raw.github.com/torworx/ovy/master/ovy.js">
</script>
<script src="http://indigounited.com/dejavu/dejavu.js">
</script>
<script>
  var __hasProp = {}.hasOwnProperty,
      __extends = function(child, parent) {
      for (var key in parent) {
        if (__hasProp.call(parent, key)) child[key] = parent[key];
      }

      function ctor() {
        this.constructor = child;
      }
      ctor.prototype = parent.prototype;
      child.prototype = new ctor();
      child.__super__ = parent.prototype;
      return child;
      };

  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 JRPerson = JRClass.extend({
    init: function(name) {
      this.name = name;
    },
    setAddress: function(country, city, street) {
      this.country = country;
      this.city = city;
      this.street = street;
    },
    sayHello: function() {
      console.log('I am ' + this.name + '. My address is ' + this.country + ', ' + this.city + ', ' + this.street + '.');
    }
  });

  var JRFrenchGuy = JRPerson.extend({
    init: function(name) {
      this._super(name);
    },
    setAddress: function(city, street) {
      this._super('France', city, street);
    }
  });

  var JRParisLover = JRFrenchGuy.extend({
    init: function(name) {
      this._super(name);
    },
    setAddress: function(street) {
      this._super('Paris', street);
    }
  });

  var EnderPerson = klass(function(name) {
    this.name = name;
  }).methods({
    setAddress: function(country, city, street) {
      this.country = country;
      this.city = city;
      this.street = street;
    }
  });

  var EnderFrenchGuy = EnderPerson.extend(function(name) {}).methods({
    setAddress: function(city, street) {
      this.supr('France', city, street);
    }
  });

  var EnderParisLover = EnderFrenchGuy.extend(function(name) {}).methods({
    setAddress: function(street) {
      this.supr('Paris', street);
    }
  });

  var ClassyPerson = Classy.$extend({
    __init__: function(name) {
      this.name = name;
    },
    setAddress: function(country, city, street) {
      this.country = country;
      this.city = city;
      this.street = street;
    }
  });

  var ClassyFrenchGuy = ClassyPerson.$extend({
    __init__: function(name) {
      this.$super(name);
    },
    setAddress: function(city, street) {
      this.$super('France', city, street);
    }
  });

  var ClassyParisLover = ClassyFrenchGuy.$extend({
    __init__: function(name) {
      this.$super(name);
    },
    setAddress: function(street) {
      this.$super('Paris', street);
    }
  });

  var PTClassPerson = PTClass.create({
    initialize: function(name) {
      this.name = name;
    },
    setAddress: function(country, city, street) {
      this.country = country;
      this.city = city;
      this.street = street;
    }
  });

  var PTClassFrenchGuy = PTClass.create(PTClassPerson, {
    initialize: function($super, name) {
      $super(name);
    },
    setAddress: function($super, city, street) {
      $super('France', city, street);
    }
  });

  var PTClassParisLover = PTClass.create(PTClassFrenchGuy, {
    initialize: function($super, name) {
      $super(name);
    },
    setAddress: function($super, street) {
      $super('Paris', street);
    }
  });

  var CoffeePerson = (function() {

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

    CoffeePerson.prototype.setAddress = function(country, city, street) {
      this.country = country;
      this.city = city;
      this.street = street;
    };

    return CoffeePerson;

  })();

  var CoffeeFrenchGuy = (function(_super) {

    __extends(CoffeeFrenchGuy, _super);

    function CoffeeFrenchGuy(name) {
      CoffeeFrenchGuy.__super__.constructor.call(this, name);
    }

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

    return CoffeeFrenchGuy;

  })(CoffeePerson);

  var CoffeeParisLover = (function(_super) {

    __extends(CoffeeParisLover, _super);

    function CoffeeParisLover(name) {
      CoffeeParisLover.__super__.constructor.call(this, name);
    }

    CoffeeParisLover.prototype.setAddress = function(street) {
      return CoffeeParisLover.__super__.setAddress.call(this, "Paris", street);
    };

    return CoffeeParisLover;

  })(CoffeeFrenchGuy);

  Ext.define('ExtPerson', {
    constructor: function(name) {
      this.name = name;
    },
    setAddress: function(country, city, street) {
      this.country = country;
      this.city = city;
      this.street = street;
    }
  });

  Ext.define('ExtChinaGuy', {
    extend: 'ExtPerson',
    constructor: function() {
      this.callParent(arguments);
    },
    setAddress: function(city, street) {
      this.callParent(['China', city, street]);
    }
  });

  Ext.define('ExtBeiJingLover', {
    extend: 'ExtChinaGuy',
    constructor: function(name) {
      this.callParent(arguments);
    },
    setAddress: function(street) {
      this.callParent(['BeiJing', street]);
    }
  });

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

  var dejavuClassFrenchGuy = dejavu.Class.declare({
    $extends: dejavuClassPerson,
    setAddress: function(city, street) {
      this.$super('France', city, street);
    }
  });

  var dejavuClassParisLover = dejavu.Class.declare({
    $extends: dejavuClassFrenchGuy,
    setAddress: function(street) {
      this.$super('Paris', street);
    }
  });

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

  var dejavuClassFrenchGuy2 = dejavu.Class.declare({
    $extends: dejavuClassPerson2,
    initialize: function (name) {
      dejavuClassPerson2.call(this, name);
    },
    setAddress: function(city, street) {
      dejavuClassPerson2.prototype.setAddress.call(this, 'France', city, street);
    }
  }, true);

  var dejavuClassParisLover2 = dejavu.Class.declare({
    $extends: dejavuClassFrenchGuy2,
    initialize: function (name) {
      dejavuClassFrenchGuy2.call(this, name);
    },
    setAddress: function(street) {
      dejavuClassFrenchGuy2.prototype.setAddress.call(this, 'Paris', street);
    }
  }, true);

  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);

  // OvyJS Define
  var OvyPerson = Ovy.define({
    constructor: function(name) {
      this.name = name;
    },
    setAddress: function(country, city, street) {
      this.country = country;
      this.city = city;
      this.street = street;
    }
  });

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

  var OvyBeijingLover = Ovy.define({
    extend: OvyChinaGuy,
    constructor: function(name) {
      OvyBeijingLover.$superclass.call(this, name);
    },
    setAddress: function(street) {
      OvyBeijingLover.$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 p3 = new JSFaceParisLover("Mary");
p3.setAddress("CH");

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

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

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

if (!instance) throw new Error("my.Class failed the `instanceof` test.");
pending…
John Resig Class
var p9 = new JRParisLover("Mary");
p9.setAddress("CH");

var instance = p9 instanceof JRParisLover &&
  p9 instanceof JRFrenchGuy &&
  p9 instanceof JRPerson;

if (!instance) throw new Error("John Resig Class failed the `instanceof` test.");
pending…
Klass
var p12 = new EnderParisLover("Mary");
p12.setAddress("CH");

var instance = p12 instanceof EnderParisLover &&
  p12 instanceof EnderFrenchGuy &&
  p12 instanceof EnderPerson;

if (!instance) throw new Error("Klass failed the `instanceof` test.");
pending…
Classy
var p15 = new ClassyParisLover("Mary");
p15.setAddress("CH");

var instance = p15 instanceof ClassyParisLover &&
  p15 instanceof ClassyFrenchGuy &&
  p15 instanceof ClassyPerson;

if (!instance) throw new Error("Classy failed the `instanceof` test.");
pending…
PTClass
var p18 = new PTClassParisLover("Mary");
p18.setAddress("CH");

var instance = p18 instanceof PTClassParisLover &&
  p18 instanceof PTClassFrenchGuy &&
  p18 instanceof PTClassPerson;

if (!instance) throw new Error("PTClass failed the `instanceof` test.");
pending…
CoffeeScript Classes
var p21 = new CoffeeParisLover("Mary");
p21.setAddress("CH");

var instance = p21 instanceof CoffeeParisLover &&
  p21 instanceof CoffeeFrenchGuy &&
  p21 instanceof CoffeePerson;

if (!instance) throw new Error("CoffeeScript Classes failed the `instanceof` test.");
pending…
augment
var p24 = new AugmentParisLover("Mary");
p24.setAddress("CH");

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

if (!instance) throw new Error("augment failed the `instanceof` test.");
pending…
Ext JS
var p27 = new ExtBeiJingLover("Mary");
p27.setAddress("CH");

var instance = p27 instanceof ExtBeiJingLover &&
  p27 instanceof ExtChinaGuy &&
  p27 instanceof ExtPerson;

if (!instance) throw new Error("Ext JS failed the `instanceof` test.");
pending…
OvyJS
var p30 = new OvyBeijingLover("Mary");
p30.setAddress("CH");

var instance = p30 instanceof OvyBeijingLover &&
  p30 instanceof OvyChinaGuy &&
  p30 instanceof OvyPerson;

if (!instance) throw new Error("OvyJS failed the `instanceof` test.");
pending…
dejavu
var p33 = new dejavuClassParisLover("Mary");
p33.setAddress("CH");

var instance = p33 instanceof dejavuClassParisLover &&
  p33 instanceof dejavuClassFrenchGuy &&
  p33 instanceof dejavuClassPerson;

if (!instance) throw new Error("dejavu failed the `instanceof` test.");
pending…
dejavu optimized
var p36 = new dejavuClassParisLover2("Mary");
p36.setAddress("CH");

var instance = p36 instanceof dejavuClassParisLover2 &&
  p36 instanceof dejavuClassFrenchGuy2 &&
  p36 instanceof dejavuClassPerson2;

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

var instance = p39 instanceof dejavuClassParisLover3 &&
  p39 instanceof dejavuClassFrenchGuy3 &&
  p39 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