When we started to work on version 2 of Kuzzle a year ago, the biggest question was what kind of promises are we going to use in Kuzzle core.
In the latest versions of Node.js (12 and 14):
- Use async/await for sequential execution of promises
- Use Bluebird for parallel execution of promises
- Bluebird retains the smallest memory footprint in all cases
- The performances of the promises were globally better in Node.js 10
These benchmarks simulate a situation in which queries are executed sequentially or in parallel with read/write blocking actions.
For each node version, we will run the sequential and then parallel benchmarks with the following commands:
To reproduce them, you can clone this Github repository: https://github.com/petkaantonov/bluebird/.
The benchmarking tools are in the benchmark/ folder.
Node.js versions tested
For this benchmark, we will only compare LTS versions of Node.js (i.e. even numbers).
This old version of Node.js was known for the poor performance of its native promises.
Promises managed with async/await were not yet available.
This version is the first to take advantage of the new promise management with async/await.
This version includes many performance enhancements to the promises.
For the first time, the native promises achieve performance comparable to Bluebird.
This release includes a significant performance gain for promises managed with async/await. (See the v8 blog)
However, there is a general decrease in performances of native promises compared to Node.js 10.
There is an improvement in performances of native promises in the latest version of Node.js.
Performance of sequential promises
We can see that since Node.js 12, sequential execution of promises is faster with async/await.
This suits us well because the use of async/await to manage promises is precisely designed for sequential sequences in order to get closer to synchronous programming.
It is also to be noted that Bluebird always retains the smallest memory footprint.
Performance of parallel promises
For the parallel execution of promises, you can see that Bluebird has up to 4x better performances than native Node.js promises.
We therefore prefer to use Bluebird for parallel promises executions.
In addition, the library has many high-level methods to facilitate the management of parallel treatments like Bluebird.map:
But what happened after Node.js 10?
If we take again the two graphs on the sequential and parallel performances, we can see that the release of Node.js 10 brought significant improvements in performances but then from Node.js 12 these performances have drastically decreased.
I didn't find anything special about it, so I asked twitter, and this led to this new issue been filed in v8's bugtracker: https://bugs.chromium.org/p/v8/issues/detail?id=10550