Get in touch over email if you want to explore further.
Some quick comments:
- I didn't notice the node version or you didn't state it. The impact from async hooks is _vastly_ different between node versions
- I need to update the package a bit, I've got a known perf improvement to add AFAIR.
- your implementation is likely to produce false positives. The trick to prevent (some) false positives is the most valuable part of the lib.
Also, take a look at the event loop utilization metric introduced last year https://m.youtube.com/watch?v=WetXnEPraYM&list=PL0CdgOSSGlBa...
And for more of my diagnostics experiments see debugging-aid package https://www.npmjs.com/package/debugging-aid
Also, there's a bunch of tools you could use before you deploy blocked-at or async hooks at all.
Note it's midnight here and I'll stop responding very soon :D
MacOS prior to X was cooperatively scheduled across the whole OS, and it was definitely breaking down and why Apple needed such a radical change. Likely you aren't cooperatively scaling on this scale, which is why it continues to work with many programs.
In some sense, the problem is that every line of code you write is essentially an event loop blocker. Sooner or later, as you roll the dice, one of them is going to end up taking longer than you thought. It's the same basic forces that make it so that nobody, no matter how experienced, really knows how their code is going to run until they put it under a profiler. There's just too much stuff going on nowadays for anyone to keep track of it all and know in advance.
But it is just one of those things you need to look at when first sitting down to decide what to implement your new system in. If you run the math and you need the n'th degree of performance and memory control, don't pick Python, for instance. If the profile of tasks you need to run is going to be very irregular and consume lots of the CPU and doesn't have easy ways to break it apart (or it would be too much developer effort to keep manually breaking these tasks apart), don't pick a cooperatively-scheduled language.
Fortunately, it's a lot easier than it used to be to try to take these particular tasks out and move them to another language and another process, while not having to rewrite the entire code base to get those bits out.
Preemptive multitasking was definitely one of the headline features of Mac OS X, but I think the other major one—protected memory—was the more important problem to solve with classic MacOS. Performance on classic MacOS was better for many common workloads than OS X, for several versions of the latter. And yes, playing a video while minimizing the window was a cool demo, and that capability is table stakes for an OS now. But the crashing bomb app demo was far more compelling for most of us Mac greybeards.
That said, cooperative concurrency in JS is a very different thing than in an OS. It’s not a panacea of course, but the typical APIs available are pervasively concurrent or trivial to make concurrent. And where that’s not enough (CPU bound workloads), all mainstream JS environments now support real threads. Granted that doesn’t mean JS is an ideal solution for CPU bound workloads… but if JS is already a prerequisite, it’s worth considering scaling out with threads before more expensive process spawning and IPC.
Or be comfortable rolling the critical parts in another language like cython, which I've done and got a 10000x performance speedup because the hot part of the code fit in the CPU cache and the rest was plain old python. There are times to start with something like Go when you're absolutely sure you'll need it, but I rarely regret starting in Python. It's usually easy enough to shift a single endpoint to another language or to use extensions to call into something faster.
Conversely, anything 'heavy' is probably too slow in Go/Rust too! We use GPUs for anything data-intensive, and the Python ecosystem is basically the best for that, similar to C/Java in earlier CPU eras. (I can see that changing in 2+ years as Arrow progresses and more investment happens.)
Other than that think it comes down to established tooling and team familiarity / preference. I do think there's no reason to start a green field Node.js project without TypeScript though.
Regular eventloop blocking by synchronous processing is the middle ground.
Performance issues with utilization of resources, too many promises or broken backpressure - that's where the fun begins.
If you can run your software locally and simulate load, just use node clinic. It's the best looking one ;)