Angular VS Knockout VS Ember

JavaScript performance comparison

Revision 2 of this test case created

Info

I saw an unfair comparison between Angular, Knockout, ExtJS, and Backbone, and it made me mad. So I created this one.

Preparation code

<!-- Jquery -->
<script src="http://code.jquery.com/jquery-1.7.2.min.js"></script>

<!-- Angular -->
<div ng-app>
  Angular:
  <span ng-controller="Ctrl" id="angList"><span ng-repeat="item in data">{{item}}</span></span>
</div>

<script src="http://code.angularjs.org/angular-1.0.1.min.js"></script>

<script>
  var Ctrl = function($scope){
    $scope.data = [];
  }
 
  angular.element(document).ready(function() {
    var ang_scope = $('#angList').scope();
   
    window.ANGclear = function(){
      ang_scope.data.splice(0, ang_scope.data.length);
      ang_scope.$digest();
    };
    window.ANGpush = function(data){
      ang_scope.data.push(data);
      ang_scope.$digest();
    };
  });
</script>



<!-- Knockout -->
<div id="koapp">
  Knockout:
  <span data-bind="foreach: data"><span data-bind="text: $data"></span></span>
</div>

<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout/2.0.0/knockout-min.js"></script>

<script>
  var KOData = ko.observableArray();
  var KOviewmodel = {data: KOData};
 
  ko.applyBindings(KOviewmodel, document.getElementById('koapp'));
  var KOclear = function (){
    KOData.splice(0, KOData().length);
  };
  var KOpush = function (data){
    KOData.push(data);
  };
</script>


<!-- Ember -->

<div id="emapp">
  Ember:
  <script type="text/x-handlebars">
    <span>
      {{#each EMapp.data}}<span>{{this}}</span>{{/each}}
    </span>
  </script>
</div>

<script>
  var ENV = {EXTEND_PROTOTYPES: false};
</script>

<script src="https://github.com/downloads/emberjs/ember.js/ember-0.9.8.1.min.js"></script>

<script>
  EMapp = Ember.Application.create({
    rootElement: $('#emapp')
  });
  EMapp.data = Ember.A();
 
  EMclear = function () {
    EMapp.data.clear();
  };
  EMpush = function (data) {
    EMapp.data.pushObject(data);
  };
</script>

 

Preparation code output

Angular: {{item}}
Knockout:
Ember:

Test runner

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

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
Angular 10
ANGclear();
for (var i = 0; i < 10; i++)
  ANGpush("ngitem");
pending…
Knockout 10
KOclear();
for (var i = 0; i < 10; i++)
  KOpush("koitem");
pending…
Ember 10
EMclear();
for (var i = 0; i < 10; i++)
  EMpush("emitem");
pending…
Angular 100
ANGclear();
for (var i = 0; i < 100; i++)
  ANGpush("ngitem");
pending…
Knockout 100
KOclear();
for (var i = 0; i < 100; i++)
  KOpush("koitem");
pending…
Ember 100
EMclear();
for (var i = 0; i < 100; i++)
  EMpush("emitem");
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:

7 comments

dain commented :

I've made a new revision with Ember 1.0pre and the difference is staggering: http://jsperf.com/angular-vs-knockout-vs-ember/10

dain commented :

Scratch that, I forgot to include Handlebars so Ember wasn't working properly.

What's up with Ember not actually rendering anything by the way?

Leo commented :

@dain It actually does render a bunch of "emitem" at the very bottom of the page :>

xxx commented :

Why here:
var KOclear = function (){ KOData.splice(0, KOData().length); };

is used method splice, but not removeAll? Looks like unfair.

Maurycy commented :

Why would you call additional function - $digest() in angular? When you add anything to $scope.data it's rendered automatic by angular if you call digest in each loop causing DOM elements to appear that's the worst idea ever since DOM operations are very slow comparing to code execute. It's better practice to generate 1000 elements output in JS then add it to DOM than add single DOM elements 1000 times

AngwyDeveloper commented :

^^ Yeah, what he said... You shit-sipper! Y U DO DIS?!

Nicholas Daley commented :

@Maurycy a call to $digest or $apply is needed to kick off angular's digest cycle, because the code was not called from angular. Same as you need $digest or $apply if you change the scope from a native javascript timeout or event handler.

Add a comment