Voyage to the most efficient loop in NodeJS (and a bit JS)

Florian "Aamu Lumi" Kauder
5 min readJul 26, 2017

In this new episode, we will try to determine what is the best way to write a loop in node.js and JS. Is the cached length myth a reality? Has StackOverflow the best answer to this problem? Is there a new best option to compute the super-fast loop? All these questions will be answered in this MythBusters!

Okay, this is really going much too far.

EDIT (11/4/19) : I’m currently doing some tests with Node 10, and the caching bug seems corrected. You can now write your loop with the good old way :

for (let i = 0; i < array.length; i++)

EDIT (31/3/18) : an explanation of loops behaviors from John Klimov :

It explains a lot of things. Many thanks to him !

EDIT (17/8/17) : I’m now running Node 8.4, and caching length is again useful.

EDIT (9/8/17) : I discovered that the trick I described in this article really exists in Hydrogen generated code. Hydrogen is the engine used in V8 until 5.9 to optimize Javascript code. The difference with the classic loop is the tricked loop will be transformed into a more simple code.

I tested the trick on the latest v8 engine which uses Turbofan. It’s version 6.2 when I did tests. And the trick was corrected. So this trick will not be available from Node 8.4 (which will use Turbofan).

If you want a bit more information : https://twitter.com/AamuLumi/status/895224348642037761

I’m currently developing an optimization library (called sanic.js) to increase native functions performance in node.js. So I need to find the best way to write some parts of code like loops.

If you type “js loop efficient” on Google (or Qwant, but he didn’t find it), you should find this topic. The top answer is (in ES6 version) :

for (let i = 0, iMax = array.length; i < iMax; i++) {}

The second answer is :

let i = array.length; while (i — ) {}

First time I read it, I was thinking StackOverflow must be right, and these answers must be the best. Another resource (a JSPerf page) show me the while version is so far powerful (note : on a WebKit browser). But you cannot use it if you need to iterate your array in ascending order.

At this point, I decided to make my own benchmark of loops with this condition :

The loop must be nondestructive. Ascending order is a plus.

Benchmark’ them all!

With this condition, I write 13 different loops on an array with for and while loops in node.js. I add the famous StackOverflow answers to the test to check if they are good. All the functions are available in this benchmark file. I know there are more functions to test, but these 13 functions are a good base.

I work with the famous Benchmark.js library to compute all my benchmarks. I’m running the latest node version (last when I’m writing this article) which is 8.1.4. Functions are executed at least 200 times to compute these statistics.

Numbers presented in this array are the number of operations by seconds. It corresponds (if I correctly understood the library) to the number of times the tested function can be executed in one second.

Okay, let’s take a look at the result array :

13 ways to loop on array (Original file)

The best StackOverflow answer is the (2). The (1) is the same version but without cached length. So yes, assign the array length to a variable is no more necessary (in node.js).

The while descending version is the (10), which is really faster than the best StackOverflow answer. But it has the disadvantage to working with a descending order.

If you look correctly, there are two fasters ways : (4) and (5). I don’t really understand why, but these writing ways are so much faster (until x2.2 on big arrays). (4) is the cached length version of the (5). So what is the code for (4) ?

let i = 0; const iMax = array.length; for(; i < iMax; i++) {}

Are you kidding me ?

Yeah. That’s ridiculous, but I test this loop on sanic.js functions (which was written with the best StackOverflow answer). And …

sanic.js gotta go faster now

These numbers correspond to the coefficient of speed gained compared to the natives node.js functions. All functions gained at least 30% of speed (except reduce but reduce was already written with this technic due to the algorithm).

So yeah, I expect the V8 to have a better optimization of this new loop. But I cannot give you a better explanation because I didn’t find it.

Time to use this good old Javascript

To confirm this hypothesis, I write another JSperf with the new case. I use Vivaldi browser which is WebKit-based, so another V8 engine. The result is the same : guys, this is the new way to write an efficient loop in JS run by V8 Engine. (Note: I also test this on Chrome. And same result.)

Vivaldi for the ❤️

We are ok for V8. But is there the same thing on other JS Engine (like Firefox) ? And one thing happens : the StackOverflow for and the new version has no difference.

Firefox — Installed just for this article

Okay. So what must we do ?

To front-end developer : if you can use this new version of the efficient loop, JUST DO IT. WebKit browsers are now the leader on the market (according to W3Schools), so a free optimization is always good.

To back-end developer : no hesitation. If you need performance, you must use it. No more to say.

Remember :

let i = 0; const iMax = array.length; for(; i < iMax; i++) {}

If you’re searching better performances in node.js native functions, take a look at my new and fresh library : sanic.js. You can test it in one line of code (a require() + a function), and it can help you to gain performance without doing anything.

And if you want to make me happy, any 💚 on this article or sanic.js are welcome. :)

This article was astounding, wasn’t it ?

--

--

Florian "Aamu Lumi" Kauder

KBDev Co-Founder - Full-Stack Developer (#NodeJS 💝) - Composer