Angular VS Knockout VS Ember VS React VS Matreshka (1000)

JavaScript performance comparison

Revision 589 of this test case created by Andrey

Preparation code

<!-- Jquery -->
<script src="https://cdn.jsdelivr.net/jquery/2.1.0/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/angularjs/1.3.14/angular.min.js"></script>
<script src="https://cdn.jsdelivr.net/knockout/3.3.0/knockout.js"></script>
<script src="https://cdn.jsdelivr.net/handlebarsjs/1.3.0/handlebars.js"></script>
<script src="https://cdn.jsdelivr.net/emberjs/1.5.0/ember.min.js"></script>
<script src="https://cdn.jsdelivr.net/react/0.10.0/react-with-addons.js"></script>
<script src="https://cdn.jsdelivr.net/matreshka/latest/matreshka.min.js"></script>

<script>
	angular.module('test', [])
		.controller('Ctrl', ['$scope', function ($scope) {

			$scope.data = [];

			window.ANGdigest = function(){
				$scope.$digest();
			};

			window.ANGclear = function () {
				$scope.data.splice(0, $scope.data.length);
			};

			window.ANGpush = function (data) {
				$scope.data.push(data + $scope.data.length);
			};

		}]);
</script>

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


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

<!-- Ember -->

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


<!-- React -->
<div id="react">
	React: <span id="reactMountNode"></span>
</div>


<!-- Matreshka -->
<div id="matreshka">
	Matreshka: <span id="matreshkaMountNode"></span>
</div>


<script>
	$(function () {
		window.KOData = ko.observableArray();
		var KOviewmodel = {data: KOData};

		var ENV = {EXTEND_PROTOTYPES: false};

		var ReactComponent = React.createClass({
			displayName: 'PerfTest',
			getInitialState: function () {
				return {data: []};
			},
			render: function () {
				var res = [];
				for (var i = 0; i < this.state.data.length; i++) {
					res.push(React.DOM.span({key: 'test' + i}, this.state.data[i]));
				}
				return React.DOM.span(null, res);
			}
		});


		var MatreshkaModel = MK.Class({
			'extends': MK.Object,
			constructor: function () {
				this.on('render', function (evt) {
					this.bindNode('value', ':sandbox', {
						setValue: function (v) {
							this.innerHTML = v;
						}
					});
				});
			}
		});

		var matreshkaApp = new MK.Class({
			'extends': MK.Array,
			Model: MatreshkaModel,
			itemRenderer: '<span>',
			constructor: function () {
				this.bindNode('sandbox', '#matreshkaMountNode');
			}
		});


		ko.applyBindings(KOviewmodel, document.getElementById('koapp'));
		window.KOclear = function () {
			KOData.splice(0, KOData().length);
		};
		window.KOpush = function (data) {
			KOData.push(data);
		};


		EMapp = Ember.Application.create({
			rootElement: '#emapp'
		});
		EMapp.data = Ember.A();

		window.EMclear = function () {
			EMapp.data.clear();
		};
		window.EMpush = function (data) {
			EMapp.data.pushObject(data);
		};


		window.reactComp = ReactComponent();
		React.renderComponent(reactComp, $('#reactMountNode')[0]);

		window.RClear = function () {
			reactComp.setState({data: []})
		};

		window.RPush = function (data) {
			window.RstateData = reactComp.state.data;
			RstateData.push(data);
		};
		
		window.RInit = function(){
			reactComp.setState({data: RstateData});
		};


		window.MKpush = function (value) {
			matreshkaApp.push({value: value});
		};

		window.MKclear = function () {
			matreshkaApp.recreate();
		};
	});
</script>
    

Preparation code output

<!-- Jquery --> <script src="https://cdn.jsdelivr.net/angularjs/1.3.14/angular.min.js"></script> <script src="https://cdn.jsdelivr.net/knockout/3.3.0/knockout.js"></script> <script src="https://cdn.jsdelivr.net/handlebarsjs/1.3.0/handlebars.js"></script> <script src="https://cdn.jsdelivr.net/emberjs/1.5.0/ember.min.js"></script> <script src="https://cdn.jsdelivr.net/react/0.10.0/react-with-addons.js"></script> <script src="https://cdn.jsdelivr.net/matreshka/latest/matreshka.min.js"></script> <script> angular.module('test', []) .controller('Ctrl', ['$scope', function ($scope) { $scope.data = []; window.ANGdigest = function(){ $scope.$digest(); }; window.ANGclear = function () { $scope.data.splice(0, $scope.data.length); }; window.ANGpush = function (data) { $scope.data.push(data + $scope.data.length); }; }]); </script> <!-- Angular --> <div ng-app="test"> Angular: <span ng-controller="Ctrl" id="angList"><span ng-repeat="item in data">{{item}}</span></span> </div> <!-- Knockout --> <div id="koapp"> Knockout: <span data-bind="foreach: data"><span data-bind="text: $data"></span></span> </div> <!-- Ember --> <div id="emapp"></div> <script type="text/x-handlebars"> Ember: <span> {{#each EMapp.data}}<span>{{this}}</span>{{/each}} </span> </script> <!-- React --> <div id="react"> React: <span id="reactMountNode"></span> </div> <!-- Matreshka --> <div id="matreshka"> Matreshka: <span id="matreshkaMountNode"></span> </div> <script> $(function () { window.KOData = ko.observableArray(); var KOviewmodel = {data: KOData}; var ENV = {EXTEND_PROTOTYPES: false}; var ReactComponent = React.createClass({ displayName: 'PerfTest', getInitialState: function () { return {data: []}; }, render: function () { var res = []; for (var i = 0; i < this.state.data.length; i++) { res.push(React.DOM.span({key: 'test' + i}, this.state.data[i])); } return React.DOM.span(null, res); } }); var MatreshkaModel = MK.Class({ 'extends': MK.Object, constructor: function () { this.on('render', function (evt) { this.bindNode('value', ':sandbox', { setValue: function (v) { this.innerHTML = v; } }); }); } }); var matreshkaApp = new MK.Class({ 'extends': MK.Array, Model: MatreshkaModel, itemRenderer: '<span>', constructor: function () { this.bindNode('sandbox', '#matreshkaMountNode'); } }); ko.applyBindings(KOviewmodel, document.getElementById('koapp')); window.KOclear = function () { KOData.splice(0, KOData().length); }; window.KOpush = function (data) { KOData.push(data); }; EMapp = Ember.Application.create({ rootElement: '#emapp' }); EMapp.data = Ember.A(); window.EMclear = function () { EMapp.data.clear(); }; window.EMpush = function (data) { EMapp.data.pushObject(data); }; window.reactComp = ReactComponent(); React.renderComponent(reactComp, $('#reactMountNode')[0]); window.RClear = function () { reactComp.setState({data: []}) }; window.RPush = function (data) { window.RstateData = reactComp.state.data; RstateData.push(data); }; window.RInit = function(){ reactComp.setState({data: RstateData}); }; window.MKpush = function (value) { matreshkaApp.push({value: value}); }; window.MKclear = function () { matreshkaApp.recreate(); }; }); </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
Angular 1000
	ANGclear();
	for (var i = 0; i < 1000; i++)
		ANGpush("ngitem");
	ANGdigest();
pending…
React 1000
	RClear();
	for (var i = 0; i < 1000; i++)
		RPush("ritem");
	RInit()
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

Angular: {{item}}
Knockout:
React:
Matreshka: