Angular forEach vs. Native for loop vs. Lodash (v71)

Revision 71 of this benchmark created by Harish on


Description

Should be quicker when caching length, also updated latest stable AngularJS! :)

Preparation HTML

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.18/angular.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.js"></script>

Setup

var __ = {
      forEachRight: function (obj, callback) {
        for (i = obj.length - 1; i >= 0; i--) {
          callback(obj[i]);
        }
      }
    };
    
    var dataset, i, retObj = {}, stats = [{
        "window": "lifetime",
        "source": "DX",
        "spend": "1642.81",
        "ideal_spend": "2989.86",
        "pace": "43",
        "impressions": "224929",
        "actions": "189",
        "cpm": "3.90",
        "ideal_cpm": "2.81",
        "cpa": "25.82"
      }, {
        "window": "yesterday",
        "source": "DX",
        "spend": "1634.57",
        "ideal_spend": "3276.75",
        "pace": "24",
        "impressions": "24771",
        "actions": "41",
        "cpm": "2.08",
        "ideal_cpm": "3.14",
        "cpa": "16.00"
      }];
    
    function runForLoop(stats) {
       var i,len = stats.length;
       for (i = 0; i < len; i++) {
          var d = stats[i],dw = d.window || 0;
          if (dw && dw === 'lifetime') {
             delete dw;
             retObj = d;
          }
       }
    }
    
    function runForEachLoop(stats) {
    stats.forEach(function(dataset) {
      if (dataset.window && dataset.window === 'lifetime') {
        delete dataset.window;
        retObj = dataset;
      }
    });
    }

Test runner

Ready to run.

Testing in
TestOps/sec
Angular forEach
angular.forEach(stats, function(dataset) {
  if (dataset.window && dataset.window === 'lifetime') {
    delete dataset.window;
    retObj = dataset;
  }
});
ready
Native For Right
for (i = stats.length - 1; i >= 0; i--) {
  dataset = stats[i];
  if (dataset.window && dataset.window === 'lifetime') {
    delete dataset.window;
    retObj = dataset;
  }
}
ready
Lodash forEachRight
_.forEachRight(stats, function(dataset) {
  if (dataset.window && dataset.window === 'lifetime') {
    delete dataset.window;
    retObj = dataset;
  }
});
ready
Array Map
stats = stats.map(function(dataset) {
  if (dataset.window && dataset.window === 'lifetime') {
    delete dataset.window;
    retObj = dataset;
  }

return dataset;
});
ready
ES5 forEach
stats.forEach(function(dataset) {
  if (dataset.window && dataset.window === 'lifetime') {
    delete dataset.window;
    retObj = dataset;
  }
});
ready
Lodash forEachLeft
_.forEach(stats, function(dataset) {
  if (dataset.window && dataset.window === 'lifetime') {
    delete dataset.window;
    retObj = dataset;
  }
});
ready
Native For Left
for (i = 0; i < stats.length; i++) {
  var dataset = stats[i];
  if (dataset.window && dataset.window === 'lifetime') {
    delete dataset.window;
    retObj = dataset;
  }
}
ready
for loop, super-cached i and stats length, simpler!
var i,len = stats.length;
for (i = 0; i < len; i++) {
  var d = stats[i],dw = d.window || 0;
  if (dw && dw === 'lifetime') {
    delete dw;
    retObj = d;
  }
}
ready
while loop
var i = -1,len = stats.length;
while(++i < len) {

  var d = stats[i],dw = d.window || 0;
  if (dw && dw === 'lifetime') {
    delete dw;
    retObj = d;
  }
}
ready
for loop using <=
var i,len = stats.length - 1;
for (i = 0; i <= len; i++) {
  var d = stats[i],dw = d.window || 0;
  if (dw && dw === 'lifetime') {
    delete dw;
    retObj = d;
  }
}
ready
Calling pre-defined "for" function
// V8 Optimized compiler function
// Implements Test Case 8 as a function
runForLoop(stats);
ready
Calling pre-defined "foreach" function
// V8 Optimized compiler function
// Implements Test Case 5 as a function
runForEachLoop(stats);
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.