I wanted to implement a game in javascript with an MVC design pattern, with each entity's state stored in a model.
So for example,
In an update loop we iterate over all models and apply the velocity attribute to the position attribute of the model. A view associated with each entity/model would then receive a position changed event, and update the representation of the entity. This would happen independently of the views render method being called in a requestAnimationFrame callback.
What I found though, through a possibly naive implementation, is that setting attributes of a model is simply too slow. As much as I prefer the architecture of this code, the framerate was significantly lower.
Should I give up on using MVC for frequently updated attributes like position?
Below, I've included some code to test aspects of setting attributes of an object. The most minimal model-like behaviour, in which an attribute is set only when the new value differs from the current, and a "changed" update event is triggered, is about 10x slower than just setting attributes directly.
Output:
> test(1000, 100, 10)
object[key]: 163 ms
object[key] if changed: 172 ms
object[key] if changed & emit backbone event: 953 ms
Backbone.Model: 4043 ms
eventsBackboneCount: 100000
var test = function(creations, iterations, keyCount){
var eventsBackbone = _.extend({}, Backbone.Events);
var eventsBackboneCount = 0;
eventsBackbone.on('all', function(){
eventsBackboneCount = eventsBackboneCount + 1;
});
var looper = function(label, create, set){
var start = (new Date()).getTime();
var data = {};
for(var i = 0; i < creations; i++){
data[i] = create(i);
}
for(var j = 0; j < iterations; j++){
for(var i = 0; i < creations; i++){
var key = ''+(j % keyCount);
set(data[i], key, Math.random());
}
}
var end = (new Date()).getTime();
console.log(''+label+': '+(end - start)+' ms');
return data;
};
looper(
'object[key]',
function(id){
return {};
},
function(datum, key, value){
datum[key] = value;
}
);
looper(
'object[key] if changed',
function(id){
return {};
},
function(datum, key, value){
if(datum[key] !== value){
datum[key] = value;
}
}
);
looper(
'object[key] if changed & emit backbone event',
function(id){
return {id:id};
},
function(datum, key, value){
if(datum[key] !== value){
datum[key] = value;
eventsBackbone.trigger('changed:'+datum.id, datum, key);
}
}
);
looper(
'Backbone.Model',
function(id){
return new Backbone.Model({});
},
function(datum, key, value){
datum.set(key, value);
}
);
console.log('eventsBackboneCount: '+eventsBackboneCount);
};