DEV Community

Cover image for Benchmarking 'for', 'while', 'for...of', and 'Array.forEach' - using Performance.now()
Muhammad A Faishal
Muhammad A Faishal

Posted on

Benchmarking 'for', 'while', 'for...of', and 'Array.forEach' - using Performance.now()

Currently, let's talk about looping in JavaScript! As we all know that there several methods to do it. Some of the methods that developers usually use are:

Developers love using Array.forEach because it's simple and easy to use. But, have you ever wondered why we have so many options for looping? Why not just get rid of the rest and stick with the best one?

Now, let's do some performance tests using Performance.now()!

Benchmarking

Here are the test cases and loops used for benchmarking.

Test Case

const iterations = ITERATION_TOTAL // 10, 100, 10000, 1000000, 10000000
const myArray = Array.from(Array(iterations).keys())

let total = 0

const start = performance.now()

// Looping method will be here

const end = performance.now()

console.log(`It took ${end - start} ms.`);
Enter fullscreen mode Exit fullscreen mode

For

for (let i = 0; i < myArray.length; i++) {
  total += myArray[i]
}
Enter fullscreen mode Exit fullscreen mode

While

let i = 0

while (i < myArray.length) {
  total += myArray[i]
  i++
}
Enter fullscreen mode Exit fullscreen mode

For...of

for (const item of myArray) {
  total += item
}
Enter fullscreen mode Exit fullscreen mode

Array.forEach

myArray.forEach((item) => {
  total += item
})
Enter fullscreen mode Exit fullscreen mode

The tests were run with Node Js v18.17.0. Each loop was tested for different iterations: 10, 100, 10,000, 1,000,000, and 10,000,000. I averaged the times I got for each iteration.

Result

Here are the results for each loop with those iterations (the lower the better):

10 Iterations

Javascript loop 10 iterations

100 Iterations

Javascript loop 100 iterations

10,000 Iterations

Javascript loop 10000 iterations

1,000,000 Iterations

Javascript loop 1000000 iterations

10,000,000 Iterations

Javascript loop 10000000 iterations

Conclusion

For Frontend stuff, it's all good to use any of the loop methods (for, while, for...of, and Array.forEach) because most websites don't usually show more than 10,000 items on a page.

But when it comes to Backend Processing, Code Validation, Linting, etc., for and while loops are still totally the way to go! 🚀

So, not everything that's cool and easy on the developer side is the best for the project. There might be some trade-offs, you know. ✨

Top comments (6)

Collapse
 
lionelrowe profile image
lionel-rowe

Bit disappointing to see for...of performs so poorly, given that it's the best level of abstraction for most situations. It's reasonable to expect a performance hit for forEach, given that it's a method call that takes a callback, but I would've expected for...of to do better given it's a built-in language feature.

I'm still gonna use for...of for most loops though, unless it's a critical path that frequently operates on very large arrays.

Collapse
 
maafaishal profile image
Muhammad A Faishal • Edited

Sure, if you are comfortable with using for...of, that's alright. It is still worth using.

Someone once said: "First, make it work, then make it better." 😄

Collapse
 
elijahtrillionz profile image
Elijah Trillionz

Really interesting experiment.
I've often seen benchmark tools returning for loop as the fastest, now I get to see it closely.
Thanks for sharing

Collapse
 
efpage profile image
Eckehard • Edited

How did you manage to measure the short loops? Referring to this document, the resolution of performance.now has to be limited for security reasons. For chorme, the minimal resolution is 0.1ms + some jitter of 0.1ms, so a loop needs to run for at least 10ms to get a reasonable result.

On my Laptop with current chrome I need to run the loop at least 10 Mio. times to get about 60ms runtime. Even then, there are some fluctiations in the results. And I add some more loop types with a bit different results:

// for..in
for (const i in myArray) {
      total += myArray[i]
}

// array.map
myArray.map((item) => { 
      total += item
})
Enter fullscreen mode Exit fullscreen mode

Here are my results:

for took 62.90 ms.
while took 68.00 ms.
for..of 122.40 ms.
for..in 1808.80 ms.
arr.forEach 123.60 ms.
arr.map 155.00 ms.

Results

So, here for..of and arr.forEach only double the runtime, map() adds some overhead as it has to return the results.

for..in for some reason was about 30 times slower. I could not figure out, why, but the situation is even worse on firefox:

for took 30.00 ms.
while took 109.00 ms.
for..of 90.00 ms.
for..in 15484.00 ms.
arr.forEach 31.00 ms.
arr.map 152.00 ms

As a bottomline we have to state, that things are much depending on the implementation on this level. So, there possibly is no general rule on this topic.

Collapse
 
maafaishal profile image
Muhammad A Faishal • Edited

I used node CLI from Node Js v18.17.0 to run the test cases in JavaScript file. It's simpler and more precise to benchmark with the iteration approach than Chrome and other browsers, due to security reason.

I actually didn't add for...in and Array.map because those methods are used in different cases... But, that's nice information, btw!

As a bottomline we have to state, that things are much depending on the implementation on this level. So, there possibly is no general rule on this topic.

Yeah, that's the reason the purpose of this post is to give results that are as accurate as possible with the same approach, machine, and conditions.

Collapse
 
jpmm profile image
jpmm

The way you setup the while and for loops seems unusally slow. I would write loops like this especially if I know the iteration count will be high:

// For
var len = myArray.length;
for (let i = 0; i < len; i++) {
  total += myArray[i]
}

// While

var i = 0,
    len = myArray.length;

while (i < len) {
  total += myArray[i]
  i++
}

// While alt.

var i = myArray.length;

while (i--) {
  total += myArray[i];
}
Enter fullscreen mode Exit fullscreen mode

Checking length of an array every loop is a huge waste of perfomance if you know the length of the array won't change inside the loop. This should outperform forEach even further.