Reputation: 15329
I'm working on a performance-intensive library and wanted to see if anyone had some ideas on how to improve the performance of this method which converts our models to a js object.
You'll see below that I've tried to employ a couple of optimization techniques based on my reading:
field = fields[i]
, etc).Here's the method I'm trying to further optimize:
toObject: function() {
var i, l, fields, field, schema, obj = {};
for(i = 0, fields = Object.keys(this._schema), l = fields.length; i < l; i++) {
field = fields[i], schema = this._schema[field];
if(!this._data.hasOwnProperty(field) || (schema.hasOwnProperty('output') && !schema[field].output)) {
continue;
}
if(schema.hasOwnProperty('collection')) {
obj[field] = [];
schema.collection.instances.forEach(function (mdl) {
obj[field].push(mdl.toObject());
});
}
obj[field] = schema.hasOwnProperty('processOut') ? schema.processOut.call(this, this._data[field]) : this._data[field];
}
return obj;
}
In particular, I'm wondering if there's a way to optimize:
schema.collection.instances.forEach(function (mdl) {
obj[field].push(mdl.toObject());
});
If I'm not mistaken, the function within the forEach is being created on each iteration. I was going to try and move it out of the main for loop, but then I lose access to field
which I need to set the property key on obj
.
I also thought about turning this into another for/loop, but then I'd have to create another set of variables like so:
// these vars would be init'd at the top of toObject or
// maybe it makes sense to put them within the parent
// for loop to avoid the additional scope lookup?
var x, xl;
for(x = 0, xl = schema.collection.instances.length; x < xl; x++) {
obj[field].push(schema.collection.instances[x].toObject());
}
This just looks a little ugly, though, to be honest - this is a situation where we are collectively willing to forgo a little readability for performance.
I realize these may be minor micro-optimizations, but they've been shown to add up in my anecdotal experience when modeling several thousands of objects.
Upvotes: 2
Views: 1907
Reputation: 106698
The for loop you have suggested is about as good as you're going to get. A couple optimizations you could take would be to avoid property lookups:
var objval = obj[field],
instances = schema.collection.instances;
for(x = 0, xl = instances.length; x < xl; ++x) {
objval.push(instances[x].toObject());
}
On a semi-related note, hasOwnProperty()
does cause a signficant performance hit (compared to something simpler like field !== undefined
).
Upvotes: 1