Knockout.js vs Backbone.js vs Direct DOM Manipulation

JavaScript performance comparison

Revision 2 of this test case created by Hallvar Helleseth

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="//cloud.github.com/downloads/SteveSanderson/knockout/knockout-2.0.0.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.3.1/underscore-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.1/backbone-min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.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.setDomLibrary(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

Test runner

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

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
Knockout.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>';
el = document.getElementById('knockout');

// Run Knockout.js
ko.applyBindings(new ViewModel(), document.getElementById('knockout'));
pending…
Direct 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>';
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…
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…

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:

1 comment

Vinny commented :

Thanks for posting this. It was an eye-opener for me.

Add a comment