Backbone vs. Ember vs. React: A Benchmark
by blesh
HTML
<script src="http://underscorejs.org/underscore-min.js"></script>
<script src="http://backbonejs.org/backbone-min.js"></script>
<script src="http://builds.handlebarsjs.com.s3.amazonaws.com/handlebars-v1.3.0.js"></script>
<script src="https://rawgithub.com/ebryn/0bbe6639da1166bef3ee/raw/c5f715bbee4200d328065fdb34b0bb49f2d748cf/ember-htmlbars-dont-use-me-anywhere-else.prod.js"></script>
<script src="http://react.zpao.com/builds/master/latest/react.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.min.js"></script>
<p>
This is a fork of <a href="http://jsfiddle.net/jashkenas/CGSd5/" target="_top">jashkenas's Ember/Backbone</a> benchmark to include React. Note that this is just a simple benchmark: you wouldn't be doing this in an actual app.
</p>
<button onclick="runBackbone()">Animate with Backbone</button>
<button onclick="runEmber()">Animate with Ember+HTMLBars</button>
<button onclick="runReact()">Animate with React</button>
<button onclick="runRawdog()">Animate with nothing</button>
<button onclick="runAngular()">Animate with Angular</button>
<p id="timing"> </p>
<div id="grid"></div>
<script type="x-html-in-html-template-in-template-weirdness" id="angular-template">
<div class="toControl">
<div class="box-view" ng-repeat="item in items track by $index">
<div class="box" style="{{item.style}}">{{item.content}}</div>
</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-htmlbars" id="htmlbars-box">
<div class="box" id="{{number}}" style="{{style}}"> {{content}}</div>
</script>
CSS
p {
font: 12px/16px Arial;
margin: 10px 10px 15px;
}
button {
font: bold 14px/14px Arial;
margin-left: 10px;
}
#grid {
margin: 10px;
}
#timing {
clear: both;
padding-top: 10px;
}
.box-view {
width: 20px; height: 20px;
float: left;
position: relative;
margin: 8px;
}
.box {
border-radius: 100px;
width: 20px; height: 10px;
padding: 5px 0;
color: #fff;
font: 10px/10px Arial;
text-align: center;
position: absolute;
}
JavaScript
// Change N to change the number of drawn circles.
var N = 100;
// The Angular implementation:
(function (){
var app = angular.module('animateApp', []);
var angularAnimate;
app.controller('MainCtrl', function($scope) {
var ctrl = this;
ctrl.count = 0;
$scope.items = [];
for(var i = 0; i < N; i++) {
$scope.items.push({});
}
angularAnimate = function() {
$scope.$apply(function (){
var count = ctrl.count += 1;
angular.forEach($scope.items, function(item) {
item.top = Math.sin(count / 10) * 10;
item.left = Math.cos(count / 10) * 10;
item.color = count % 255;
item.content = count % 100;
item.style = 'background-color:rgb(0,0,' + item.color +');left:' + item.left + 'px;top:' + item.top +'px';
});
});
};
console.log('controller instantiated');
});
var angularInit = function() {
//This is a really weird way to test anything, but I'm game.
var html = $('#angular-template').html();
var el = angular.element(html);
var grid = angular.element('#grid');
grid.append(el);
el.attr('ng-controller', 'MainCtrl');
angular.bootstrap(grid, ['animateApp']);
};
window.runAngular = function() {
reset();
angularInit();
console.log('benchmark start');
benchmarkLoop(angularAnimate);
};
}());
// The Backbone implementation:
(function(){
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) *...