Node.js

Beware the performance cost of async_hooks (Node 8)

I was excited about async_hooks having finally landed in Node.js 8, as it would enable me to share important troubleshooting information with all code involved in handling a particular request. However it turned out to have terrible impact of our CPU usage (YMMV):
 
 
 
 
 
 
 
 
async_hooks

This was quite extreme and is likely related to the way how our application works and uses Promises. Do your own testing to measure the actual impact in your app.

However I am not the only one who has seen some performance hit from async_hooks – see https://github.com/bmeurer/async-hooks-performance-impact, in particular:

Here the results of running the Promise micro benchmarks with and without async_hooks enabled:

BenchmarkNode 8.9.4Node 9.4.0
Bluebird-doxbee (regular)226 ms189 ms
Bluebird-doxbee (init hook)383 ms341 ms
Bluebird-doxbee (all hooks)440 ms411 ms
Bluebird-parallel (regular)924 ms696 ms
Bluebird-parallel (init hook)1380 ms1050 ms
Bluebird-parallel (all hooks)1488 ms1220 ms
Wikipedia (regular)993 ms804 ms
Wikipedia (init hook)2025 ms1893 ms
Wikipedia (all hooks)2109 ms2124 ms

To confirm the impact of async_hook on our app, I have performed 3 performance tests:

CPU usage without async_hooks (Node 8)

It is difficult to see but the mean CPU usage is perhaps around 60% here.

async_hooks

CPU usage with “no-op” async_hooks (Node 8)

Here the CPU jumped to 100%.

async_hooks

CPU usage with “no-op” async_hooks (Node 11)

The same as above, but using Node 11 for comparison. I recorded it for just a few minutes but the CPU usage is still around 100%:

async_hooks

The code

This is the relevant code:

  
 const asyncHooks = require('async_hooks'); // Node 8.9+
const querystring = require('querystring');
const crypto = require("crypto");

const context = {};

function createHooks() {
    function init(asyncId, type, triggerId, resource) {
        // if (context[triggerId]) {
        //     context[asyncId] = context[triggerId];
        // }
    }

    function destroy(asyncId) {
        // delete context[asyncId];
    }

    const asyncHook = asyncHooks.createHook({ init, destroy });

    asyncHook.enable();
}

createHooks()
Published on Web Code Geeks with permission by Jakub Holy, partner at our WCG program. See the original article here: Beware the performance cost of async_hooks (Node 8)

Opinions expressed by Web Code Geeks contributors are their own.

Jakub Holy

Jakub is an experienced Java[EE] developer working for a lean & agile consultancy in Norway. He is interested in code quality, developer productivity, testing, and in how to make projects succeed.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button