doremi
doremi

Reputation: 15329

Optimizing Nested For Loop

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:

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

Answers (1)

mscdex
mscdex

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

Related Questions