Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript For loop VS JQuery Each: strange result

I've read several questions / articles about this subject and I tested in my solution that the same block of code using for is most of the times faster than each.

However my question is related to the fact than in my page where I've around 30 "loops" the starting results using each were around 5300ms (average) with max value of 5900ms and minimum of 4800ms.

And after I've changed them to for and the end result surprisingly is slower, takes more time as the previous average (and never got lower than 4800ms and got even higher than 6000ms)..... but when I place console.time('Time') console.timeEnd('Time') in each single "loop block" I get the expected result (FOR is faster).

How is it possible that the global "time" is SLOWER using for than each?

Could please you point me some possible reasons?

P.S.- The full source-code is huge and the important part here is that the only change is: loops each converted to for.

Sample used for the For loop

var l = list.length;  
for (var i=0;i<l; i++) {  

}

Sample used for the Each loop

$.each(list, function (i, item) {

});

Update #1

  • Times are measured using console.time('Time') console.timeEnd('Time'). For global time I just use one "counter". For multiple counters I use different names of course.
  • During all this "process" there are no Ajax requests, so the time different isn't connected to this.

Update #2

  • As @epascarello requested: the "inner code" of each loop was never changed and it should not be the reason, even more when we access this objects the same way (using For or Each ) list[i].SomeProperty, imho the time differences could never be blamed to the inner code (I think).

Update #3

  • Sometimes I am using Cascading "loops" using different variables i, ii, iii.
  • I often "reuse" variables inside the same function:

var l = list1.length; ...; l = list2.length;

The same applies to the for variables i, ii, iii.

Update #4

I notice a strange behavior in Chrome: the following pattern uses to repeat several times, going down for a while and then spikes up again.

  • DrawGUI: 6159.000ms UP AGAIN
  • DrawGUI: 5990.000ms going down
  • DrawGUI: 5804.000ms going down
  • DrawGUI: 5416.000ms going down
  • DrawGUI: 5315.000ms going down
  • DrawGUI: 5311.000ms going down
  • DrawGUI: 5325.000ms
  • DrawGUI: 5248.000ms going down
  • DrawGUI: 5010.000ms going down
  • DrawGUI: 4886.000ms going down
  • DrawGUI: 5645.000ms *UP AGAIN *
  • DrawGUI: 5247.000ms
  • DrawGUI: 5446.000ms

During all this testes I close all the other chrome tabs and unnecessary applications. Trying to minimize unstable CPU availability.

like image 698
Dryadwoods Avatar asked Jan 29 '13 13:01

Dryadwoods


1 Answers

Since you are benchmarking empty loops you give the JIT (just in time compiler) plenty of room for optimizations. It might be the case that the each call is removed all together as it has no side effects. The for loop however must run as the i is defined in the scope containing the for loop and not inside the for loop.

(function() {
    for (var i=0; i<10; i++) {}
    console.log(i); // outputs 10
})();

vs

(function() {
    [0,1,2,3,4,5,6,7,8,9].forEach(function(i) {});
    console.log(i); // i is not declared
})();

That is also the reasons why JSLint/JSHint complains about i being declared twice for the following code:

for (var i=0; i<10; i++) {}
for (var i=0; i<10; i++) {}
like image 80
bikeshedder Avatar answered Oct 23 '22 17:10

bikeshedder