Backbone associations speed suite (v15)

Revision 15 of this benchmark created on


Preparation HTML

<script src="https://ajax.googleapis.com/ajax/libs/prototype/1/prototype.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore.js">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.2.3/backbone.js">
</script>
<script src="https://dhruvaray.github.com/backbone-associations/backbone-associations.js">
</script>
<script src="https://pauluithol.github.io/Backbone-relational/backbone-relational.js">
</script>

Setup

var _getDepartments = function() {
    var loc1 = {
      add1: "P.O Box 3899",
      zip: "94404",
      state: "CA"
    };
    var loc2 = {
      add1: "P.O Box 4899",
      zip: "95502",
      state: "CA"
    };
    return [{
      name: 'R&D',
      number: '23',
      locations: [
        loc1,
        loc2
      ]
    }, {
      name: 'Marketing',
      number: '24',
      locations: [
        loc1,
        loc2
      ]
    }];
  };
  
  
  var getEmployees = function(count) {
    !count && (count = 10);
    var result = {
      name: 'comp' + count,
      employees: []
    };
    var departmentData = _getDepartments();
    for (var i = 0; i < count; i++) {
      var emp = {
        fname: 'fname' + i,
        lname: 'lname' + i,
        age: (function() {
          var age = parseInt(Math.random() * 100);
          return age < 20 ? age + 20 : age > 65 ? 65 : age;
        })(),
        sex: (function() {
          return (parseInt(Math.random() * 100) % 2) ? 'M' : 'F';
        })(),
        works_for: (function() {
          return departmentData[(parseInt(Math.random() * 100) % 2)];
        })()
      };
      result.employees.push(emp);
    }
    return result;
  };
  
  var getExperimentalSetup = function(substrateCount, chemicalCount) {
    var substrates = [],
      chemicals = [];
    for (var i = 0; i < substrateCount; i++) {
      substrates.push({
        id: i,
        name: "substrate" + i
      });
    }
    for (var i = 0; i < chemicalCount; i++) {
      chemicals.push({
        id: i,
        name: "chemical" + i
      });
    }
    return {
      substrates: substrates,
      chemicals: chemicals
    }
  };
  
  // Associated Model  
  var associatedModel = {};
  
  
  associatedModel.Location = Backbone.AssociatedModel.extend({
    defaults: {
      add1: "",
      add2: null,
      zip: "",
      state: ""
    }
  });
  
  associatedModel.Department = Backbone.AssociatedModel.extend({
    relations: [{
      type: Backbone.Many,
      key: 'locations',
      relatedModel: associatedModel.Location
    }],
    defaults: {
      name: '',
      locations: [],
      number: -1
    }
  });
  
  associatedModel.Employee = Backbone.AssociatedModel.extend({
    relations: [{
      type: Backbone.One,
      key: 'works_for',
      relatedModel: associatedModel.Department
    }],
    validate: function(attr) {
      return (attr.sex && attr.sex != "M" && attr.sex != "F") ? "invalid sex value" : undefined;
    },
    defaults: {
      sex: 'M',
      //{F,M}
      age: 0,
      fname: "",
      lname: "",
      works_for: {}
    }
  });
  
  associatedModel.Trial = Backbone.AssociatedModel.extend({
    relations: [{
      type: Backbone.One,
      key: 'employee',
      relatedModel: associatedModel.Employee
    }],
    defaults: {
      name: '',
      employee: {}
    }
  });
  
  associatedModel.Chemical = Backbone.AssociatedModel.extend({
    defaults: {
      name: '',
      experiments: []
    }
  });
  
  associatedModel.Substrate = Backbone.AssociatedModel.extend({
    defaults: {
      name: '',
      experiments: []
    }
  });
  
  associatedModel.Experiment = Backbone.AssociatedModel.extend({
    relations: [{
      type: Backbone.Many,
      key: 'trials',
      relatedModel: associatedModel.Trial
    }, {
      type: Backbone.One,
      key: 'chemical',
      relatedModel: associatedModel.Chemical
    }, {
      type: Backbone.One,
      key: 'substrate',
      relatedModel: associatedModel.Substrate
    }],
    defaults: {
      trials: [],
      chemical: {},
      substrate: {}
    }
  });
  
  associatedModel.Company = Backbone.AssociatedModel.extend({
    relations: [{
      type: Backbone.Many,
      key: 'employees',
      relatedModel: associatedModel.Employee
    }, {
      type: Backbone.Many,
      key: 'chemicals',
      relatedModel: associatedModel.Chemical
    }, {
      type: Backbone.Many,
      key: 'substrates',
      relatedModel: associatedModel.Substrate
    }, {
      type: Backbone.Many,
      key: 'experiments',
      relatedModel: associatedModel.Experiment
    }],
    defaults: {
      name: '',
      employees: [],
      chemicals: [],
      substrates: [],
      experiments: []
    }
  });
  
  // Relational Model    
  var relationalModel = {};
  relationalModel.Location = Backbone.RelationalModel.extend({
    defaults: {
      add1: "",
      add2: null,
      zip: "",
      state: ""
    }
  });
  
  relationalModel.Department = Backbone.RelationalModel.extend({
    relations: [{
      type: Backbone.HasMany,
      key: 'locations',
      relatedModel: relationalModel.Location
    }],
    defaults: {
      name: '',
      locations: [],
      number: -1
    }
  });
  
  relationalModel.Employee = Backbone.RelationalModel.extend({
    relations: [{
      type: Backbone.HasOne,
      key: 'works_for',
      relatedModel: relationalModel.Department
    }],
    validate: function(attr) {
      return (attr.sex && attr.sex != "M" && attr.sex != "F") ? "invalid sex value" : undefined;
    },
    defaults: {
      sex: 'M',
      //{F,M}
      age: 0,
      fname: "",
      lname: "",
      works_for: {}
    }
  });
  
  relationalModel.Trial = Backbone.RelationalModel.extend({
    relations: [{
      type: Backbone.HasOne,
      key: 'employee',
      relatedModel: relationalModel.Employee
    }],
    defaults: {
      name: '',
      employee: {}
    }
  });
  
  relationalModel.Chemical = Backbone.RelationalModel.extend({
    defaults: {
      name: '',
      experiments: []
    }
  });
  
  relationalModel.Substrate = Backbone.RelationalModel.extend({
    defaults: {
      name: '',
      experiments: []
    }
  });
  
  relationalModel.Experiment = Backbone.RelationalModel.extend({
    relations: [{
      type: Backbone.HasMany,
      key: 'trials',
      relatedModel: relationalModel.Trial
    }, {
      type: Backbone.HasOne,
      key: 'chemical',
      relatedModel: relationalModel.Chemical
    }, {
      type: Backbone.HasOne,
      key: 'substrate',
      relatedModel: relationalModel.Substrate
    }],
    defaults: {
      name: '',
      trials: [],
      chemical: {},
      substrate: {}
    }
  });
  
  relationalModel.Company = Backbone.RelationalModel.extend({
    relations: [{
      type: Backbone.HasMany,
      key: 'employees',
      relatedModel: relationalModel.Employee
    }, {
      type: Backbone.HasMany,
      key: 'chemicals',
      relatedModel: relationalModel.Chemical
    }, {
      type: Backbone.HasMany,
      key: 'substrates',
      relatedModel: relationalModel.Substrate
    }, {
      type: Backbone.HasMany,
      key: 'experiments',
      relatedModel: relationalModel.Experiment
    }],
    defaults: {
      name: '',
      employees: [],
      chemicals: [],
      substrates: [],
      experiments: []
    }
  });
  
  var employeeCollection = getEmployees(100);
  var experimentalSetup = getExperimentalSetup(5, 25);
  
  // construstruction
  
  var buildExperiments = function(company) {
    n = 0
    company.get('chemicals').each(function(chemical) {
      company.get('substrates').each(function(substrate) {
        company.get('experiments').add({
          number: n++,
          chemical: chemical,
          substrate: substrate,
        });
      });
    });
  };
  
  var runExperiments = function(company, nExperiments, nTrials, nData) {
    company.get('employees').each(function(employee) {
      experiment = company.get('experiments').at(parseInt(Math.random() * company.get('experiments').length));
      for (var i = 0; i < nTrials; i++) {
        experiment.get('trials').add({
          name: employee.get('name') + i,
          employee: employee,
          tick: 0
        });
        var trial = experiment.get('trials').last()
        for (var d = 0; d < nData; d++) {
          trial.set('tick', trial.get('tick') + 1);
        }
      }
    });
  }

Test runner

Ready to run.

Testing in
TestOps/sec
backbone-associations
// async test
var company = new associatedModel.Company();
company.set(employeeCollection);
company.set(experimentalSetup);
buildExperiments(company);
runExperiments(company, 4, 3, 3);
ready
backbone-relational
var company = new relationalModel.Company();
company.set(employeeCollection);
company.set(experimentalSetup);
buildExperiments(company);
runExperiments(company, 4, 3, 3);
ready

Revisions

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