Knockout.js vs Backbone.js vs Direct DOM Manipulation

JavaScript performance comparison

Revision 25 of this test case created by

Preparation code

<div id="test">
  <ul id="knockout" data-bind="foreach: jokes">
    <li data-bind="text: joke" />
  </ul>
  <ul id="dom">
  </ul>
  <ul id="backbone">
  </ul>
</div>
<script type="text/template" id="backbone-template">
  < li > < %= joke % > < /li>
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.0.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.10/backbone-min.js"></script>
      
<script>
Benchmark.prototype.setup = function() {
  // Reset DOM
  var el = document.getElementById('test');
  el.outerHTML = '<div id="test"><ul id="knockout" data-bind="foreach: jokes"><li data-bind="text: joke"/></ul><ul id="dom"></ul><ul id="backbone"></ul></div>';
  
  var jokes = [{
    joke: "How many programmers does it take to change a light bulb? None – It’s a hardware problem"
  }, {
    joke: "Programming is like sex: One mistake and you have to support it for the rest of your life."
  }, {
    joke: "There are three kinds of lies: Dark Lies, white lies, and benchmarks."
  }];
  
  /* Knockout.js */
  
  function ViewModel() {
    this.jokes = jokes;
  }
  
  /* Backbone.js */
  Backbone.$ = jQuery;
  
  var Model = Backbone.Model.extend({
    defaults: function() {
      return {
        joke: null
      };
    }
  });
  
  var Collection = Backbone.Collection.extend({
    model: Model
  });
  
  var collection = new Collection();
  
  var View = Backbone.View.extend({
    tagName: 'li',
    template: _.template($('#backbone-template').html()),
  
    render: function() {
      $(this.el).html(this.template(this.model.toJSON()));
      return this;
    }
  });
  
  var AppView = Backbone.View.extend({
    el: $('#backbone'),
    initialize: function() {
      collection.bind('add', this.addOne, this);
      collection.bind('reset', this.addAll, this);
  
      collection.reset(jokes);
    },
    addOne: function(joke) {
      var view = new View({
        model: joke
      });
      $('#backbone').append(view.render().el);
    },
  
    addAll: function() {
      collection.each(this.addOne);
    },
  });

};
</script>

Preparation code output

<div id="test"> <ul id="knockout" data-bind="foreach: jokes"> <li data-bind="text: joke" /> </ul> <ul id="dom"> </ul> <ul id="backbone"> </ul> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.0.0/knockout-min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.10/backbone-min.js"></script>

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in CCBot 2.0.0 / Other 0.0.0
Test Ops/sec
Knockout.js
// Reset DOM
var el = document.getElementById('test');
el.innerHTML = '<ul id="knockout" data-bind="foreach: jokes"><li data-bind="text: joke"/></ul>';
el = document.getElementById('knockout');

// Run Knockout.js
ko.applyBindings(new ViewModel(), el);
pending…
JQuery DOM Manipulation
// Reset DOM
var el = document.getElementById('test');
el.outerHTML = '<div id="test"><ul id="knockout" data-bind="foreach: jokes"><li data-bind="text: joke"/></ul><ul id="dom"></ul><ul id="backbone"></ul></div>';

// Manipulate DOM
for (var i in jokes) {
  $('#dom').append($('<li></li>').append(jokes[i].joke));
}
pending…
Backbone.js
// Reset DOM
var el = document.getElementById('test');
el.outerHTML = '<div id="test"><ul id="knockout" data-bind="foreach: jokes"><li data-bind="text: joke"/></ul><ul id="dom"></ul><ul id="backbone"></ul></div>';

// Run Backbone.js
collection = new Collection(); // workaround: collection.reset doesn't seem to clear old items
var v = new AppView();
pending…
Direct DOM manipulation
// Reset DOM
var el = document.getElementById('test');
el.innerHTML = '<ul id="dom"></ul>';
el = document.getElementById('dom');

// Manipulate DOM
for(var i in jokes) {
    var li = document.createElement('li');
    li.appendChild(document.createTextNode(jokes[i].joke));
    el.appendChild(li);
}
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.

0 Comments