CanJS EJS Live Binding Performance
JavaScript performance comparison
Info
Comparison between CanJS, Backbone, Ember, YUI and Ember.
Test renders 100 circles and updates the content and style of each.
Based on demo here: http://jsfiddle.net/JMWf4/4/
Preparation code
<script src="http://underscorejs.org/underscore-min.js">
</script>
<script src="http://donejs.com/examples/todo/zepto/zepto.0.8-focusblur.js">
</script>
<script src="http://donejs.com/can/dist/edge/can.zepto.js">
</script>
<script src="http://backbonejs.org/backbone-min.js">
</script>
<script src="http://cloud.github.com/downloads/SteveSanderson/knockout/knockout-2.0.0.js">
</script>
<script type="text/ejs" id="ejs-template">
<% list(boxes, function( box ) { %>
<div class="box-view">
<div class="box" id="box-<%= box.count %>" style="<%= box.style() %>">
<%= box.content() %>
</div>
</div>
<% }) %>
</script>
<script type="x-template" id="underscore-template">
<div class="box" id="box-<%= number %>" style="top: <%= top %>px; left: <%= left %>px; background: rgb(0,0,<%= color %>);">
<%= content %>
</div>
</script>
<script type="text/x-handlebars" id="handlebars-template" data-template-name="box">
<div class="box" {{bindAttr id="model.number" style="model.style"}}>
{{ model.content }}
</div>
</script>
<script type="text/x-template" id="knockout-template">
<div data-bind="foreach: boxes">
<div class="box-view">
<div class="box" data-bind="style: {top: top(), left: left(), background: color()}, text: content()"></div>
</div>
</div>
</script>
<script type="text/x-yui-handlebars" id="yui-handlebars-template">
<div class="box" id="box-{{number}}" style="top: {{top}}px; left: {{left}}px; background: rgb(0,0,{{color}});">
{{content}}
</div>
</script>
<div id="grid"></div>
<script>
Benchmark.prototype.setup = function() {
window.N = 100;
window.timeout = null;
window.iterations = 1;
window.reset = function() {
$('#gridcan').empty();
$('#gridko').empty();
$('#gridb').empty();
clearTimeout(timeout);
};
(function() {
var canIterations = 0,
Box = function() {
return {
count: 0,
top: function() {
return (Math.sin(this.count / 10) * 10) + 'px'
},
left: function() {
return (Math.cos(this.count / 10) * 10) + 'px'
},
color: function() {
return 'rgb(0,0,' + (this.count) % 255 + ')'
},
content: function() {
return this.attr('count') % 100
},
tick: function() {
this.attr('count', (this.attr('count') + 1));
},
style: function() {
this.attr('count');
return 'top: ' + this.top() + '; left: ' + this.left() + '; background: ' + this.color() + ';';
}
}
};
window.canInit = function() {
boxes = new can.Observe.List();
for (var i = 0; i < N; i++) {
boxes.push(new Box());
}
$('#gridcan').append(can.view('ejs-template', {
boxes: boxes
}));
};
var canAnimate = function() {
if (canIterations < iterations) {
for (var i = 0; i < N; i++) {
boxes[i].tick();
}
window.timeout = _.defer(canAnimate);
} else {
deferred.resolve();
return;
}
canIterations++;
};
window.runCan = function() {
//reset();
canIterations = 0;
//canInit();
canAnimate();
};
})();
(function() {
var backboneIterations = 0;
var Box = Backbone.Model.extend({
defaults: {
top: 0,
left: 0,
color: 0,
content: 0
},
initialize: function() {
this.count = 0;
},
tick: function() {
var count = this.count += 1;
this.set({
top: Math.sin(count / 10) * 10,
left: Math.cos(count / 10) * 10,
color: (count) % 255,
content: count % 100
});
}
});
var BoxView = Backbone.View.extend({
className: 'box-view',
template: _.template($('#underscore-template').html()),
initialize: function() {
this.model.bind('change', this.render, this);
},
render: function() {
this.$el.html(this.template(this.model.attributes));
return this;
}
});
var boxes;
window.backboneInit = function() {
boxes = _.map(_.range(N), function(i) {
var box = new Box({
number: i
});
var view = new BoxView({
model: box
});
$('#gridb').append(view.render().el);
return box;
});
};
var backboneAnimate = function() {
if (backboneIterations < iterations) {
for (var i = 0, l = boxes.length; i < l; i++) {
boxes[i].tick();
}
window.timeout = _.defer(backboneAnimate);
} else {
deferred.resolve();
return;
}
backboneIterations++;
};
window.runBackbone = function() {
//reset();
backboneIterations = 0
//backboneInit();
backboneAnimate();
};
})();
(function() {
var knockoutIterations = 0;
var Box = function() {
this.count = ko.observable(0);
this.top = function() {
return (Math.sin(this.count() / 10) * 10) + 'px'
};
this.left = function() {
return (Math.cos(this.count() / 10) * 10) + 'px'
};
this.color = function() {
return 'rgb(0,0,' + (this.count()) % 255 + ')'
};
this.content = function() {
return this.count() % 100
};
this.tick = function() {
this.count(this.count() + 1);
}
}
var ViewModel = function(num) {
this.num = num;
this.boxes = ko.observableArray();
for (var i = 0; i < num; i++) {
this.boxes.push(new Box())
}
}
var knockoutAnimate = function() {
if (knockoutIterations < iterations) {
for (var i = 0, l = vm.boxes().length; i < l; i++) {
vm.boxes()[i].tick();
}
window.timeout = _.defer(knockoutAnimate);
} else {
deferred.resolve();
return;
}
knockoutIterations++;
}
window.knockoutInit = function(){
//knockoutIterations = 0;
$('#gridko').html($('#knockout-template').html());
vm = new ViewModel(100)
ko.applyBindings(vm, $('#gridko')[0]);
}
window.runKnockout = function() {
knockoutIterations = 0;
knockoutAnimate();
};
})();
canInit();
backboneInit();
knockoutInit();
};
Benchmark.prototype.teardown = function() {
window.reset()
};
</script>
Preparation code output
Test runner
Warning! For accurate results, please disable Firebug before running the tests. (Why?)
Java applet disabled.
| Test | Ops/sec | |
|---|---|---|
CanJS |
|
pending… |
Backbone |
|
pending… |
Knockout |
|
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:
- Revision 1: published by Curtis Cummings
- Revision 2: published by Curtis Cummings
- Revision 5: published by Curtis Cummings
- Revision 6: published
- Revision 7: published by Curtis Cummings
- Revision 8: published
- Revision 9: published by Curtis Cummings
- Revision 11: published
- Revision 12: published
- Revision 15: published
- Revision 16: published
- Revision 20: published by Stan
- Revision 21: published
- Revision 22: published
- Revision 27: published and last updated
- Revision 28: published
- Revision 29: published
0 comments