jsPerf.app is an online JavaScript performance benchmark test runner & jsperf.com mirror. It is a complete rewrite in homage to the once excellent jsperf.com now with hopefully a more modern & maintainable codebase.
jsperf.com URLs are mirrored at the same path, e.g:
https://jsperf.com/negative-modulo/2
Can be accessed at:
https://jsperf.app/negative-modulo/2
Angular.js, Knockout.js, Ractive.js, Ant.js 的一个性能测试.
<style type="text/css">
.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;
}
</style>
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script src="http://underscorejs.org/underscore-min.js"></script>
<script src="http://backbonejs.org/backbone-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.min.js"></script>
<script src="http://knockoutjs.com/downloads/knockout-3.0.0.js"></script>
<script src="https://rawgithub.com/antjs/ant.js/v0.2.2/dist/ant.min.js"></script>
<script src="https://rawgithub.com/RactiveJS/Ractive/master/release/0.3.7/Ractive.min.js"></script>
<div id="bb-box"></div>
<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>
<div id="ag-box" ng-app ng:controller="animationCtrl">
<div class="box-view" ng:repeat="box in boxes">
<div class="box" ng:style="{top: box.top+'px', left: box.left+'px', background: 'rgb(0,0,'+box.color+')'}">{{box.content}}</div>
</div>
</div>
<div id="ko-box">
<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>
</div>
<div id='ra-box'></div>
<script type="text/x-handlebars" id="ractive-template">
{{#boxes}}
<div class="box-view">
<div class="box" style='top: {{top}}px; left: {{left}}px;background-color: rgb(0, 0, {{color}})'>{{content}}</div>
</div>
{{/boxes}}
</script>
<div id='ant-box'>
<div class="box-view" a-repeat="{{boxes}}">
<div class="box" a-style='top: {{top}}px; left: {{left}}px;background-color: rgb(0, 0, {{color}})'>{{content}}</div>
</div>
</div>
<script type="text/javascript">
// Change N to change the number of drawn circles.
var N = 100;
// 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) * 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;
var backboneInit = function() {
boxes = _.map(_.range(N), function(i) {
var box = new Box({number: i});
var view = new BoxView({model: box});
$('#bb-box').append(view.render().el);
return box;
});
};
var backboneAnimate = function() {
for (var i = 0, l = boxes.length; i < l; i++) {
boxes[i].tick();
}
};
backboneInit();
window.runBackbone = function() {
backboneAnimate();
};
})();
// The angular implementation:
function animationCtrl($scope, $window, $rootScope) {
var self = this;
var start, counter = 0;
$scope.count = 0;
$scope.boxes = new Array();
$scope.Box = function(n) {
this.number = n;
this.top = 0;
this.left = 0;
this.color = 0;
this.content = 0;
this.count = 0;
this.tick = function() {
var count = this.count += 1;
this.top = Math.sin(count / 10) * 10;
this.left = Math.cos(count / 10) * 10;
this.color = count % 255;
this.content = count % 100;
}
}
$scope.angularjsInit = function() {
for (var i = 0; i < N; i++) {
$scope.boxes[i] = new $scope.Box(i);
}
}
$scope.angularjsAnimate = function() {
if (counter == 0) start = new Date().getTime();
counter += 1;
for (var i = 0; i < N; i++) {
$scope.boxes[i].tick();
}
$rootScope.$apply();
}
$scope.angularjsInit();
window.runAngularjs = function() {
$scope.angularjsAnimate();
}
}
// The Knockout implementation:
(function(){
var Box = function() {
var that = this;
that.count = ko.observable(0);
that.top = ko.computed(function(){ return (Math.sin(that.count() / 10) * 10) + 'px'});
that.left = ko.computed(function(){ return (Math.cos(that.count() / 10) * 10) + 'px'});
that.color = ko.computed(function() { return 'rgb(0,0,' + (that.count()) % 255 + ')'});
that.content = ko.computed(function() { return that.count() % 100});
this.tick = function() {
that.count(that.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() {
for (var i = 0, l = vm.boxes().length; i < l; i++) {
vm.boxes()[i].tick();
}
}
var vm = new ViewModel(N)
ko.applyBindings(vm, $('#ko-box')[0]);
window.runKnockout = function() {
knockoutAnimate();
};
})();
// The Ractive implementation:
(function(){
var boxes = [];
for(var i = 0; i < N; i++){
boxes.push({
color: 0,
top: 0,
left: 0,
content: 0
});
}
var Box = Ractive.extend({
tick: function(){
var count = this.count = this.count+1;
for(var i = 0; i < N; i++){
this.set('boxes.' + i, {
top: Math.sin(count / 10) * 10,
left: Math.cos(count / 10) * 10,
color: count % 255,
content: count % 100
});
}
},
init: function() {
this.count = 0;
}
});
var box = new Box({
el: 'ra-box',
template: $('#ractive-template').html(),
data: {boxes: boxes}
});
window.runRactive = function() {
box.tick();
}
})();
// The Ant.js implementation:
(function(){
var boxes = [];
for(var i = 0; i < N; i++){
boxes.push({
color: 0,
top: 0,
left: 0,
content: 0
});
}
var Box = Ant.extend({
tick: function(){
var count = this.count = this.count+1;
for(var i = 0; i < N; i++){
this.set('boxes.' + i, {
top: Math.sin(count / 10) * 10,
left: Math.cos(count / 10) * 10,
color: count % 255,
content: count % 100
});
}
},
init: function() {
this.count = 0;
}
});
var box = new Box($('#ant-box')[0], {
data: {boxes: boxes}
});
window.runAnt = function() {
box.tick();
}
})();
</script>
Ready to run.
Test | Ops/sec | |
---|---|---|
backbone |
| ready |
angular |
| ready |
knockout |
| ready |
ractive |
| ready |
ant.js |
| ready |
You can edit these tests or add more tests to this page by appending /edit to the URL.