Hacker News new | ask | show | jobs
by eurleif 5367 days ago
I don't think using, say, 500ms worth of CPU is all that unusual of a need. If you try to do that with node.js, everything in your program will be blocked completely for 500ms. It doesn't make node.js useless, or 'cancer', but it is a real limitation.
3 comments

A billion front-end calculations to display a webpage sounds like a hell of a lot to me. If that is common, then you can only do 2 reqs/sec/core either threaded or evented. (point 1).

If the 500ms request is rare, then occasionally some requests will be delayed vs a threaded setup. Keep in mind, that V8 is about 1 order of magnitude faster than CPython/PHP.

There are nodejs web worker implementations to help with that kind of problem:

https://github.com/pgriess/node-webworker

If you use webworkers for cpu-intensive tasks (like fib), nodejs will perform just as well as all the other web frameworks out there.

But it does not fix the issue of e.g. having used a quadratic algorithm which is breaking your server because in production a user is shoving an order of magnitude more data than you expected (or tested for): you used that algorithm in-request because it was fast. Now it's not fast anymore and your production is getting killed. That's all there is to it, until you fix your code the application is not degraded, it's DOS'd every time that user does something.

And if you do consider workers (because you don't have a better algorithm), what happens for the cheap version? Do you offload it to a worker as well, potentially incurring a spin-off cost greater than the cost of the computation itself, or do you end up with two different codepaths (one sync and one async, just to ensure you're getting as complex as you can) depending on the computation's expected duration?

Just offload it to a child process/worker, or use a job queue.

How exactly would you avoid that 500ms block in other platforms?

The platform does it: other requests are handled by other threads or processes (pooled or not), one request is going to consume 500ms and the rest will keep on trucking concurrently. Unless you've gone above the capacities of the machine itself, other requests will be little to not affected.
just as in node where you run multiple processes against the same socket using something like https://github.com/LearnBoost/cluster
That's not avoiding it. The thread in question will still block for 500ms. The same holds true for a multi-process node app.
The point is that in a multi-thread architecture, you can still serve requests on the other threads. In a single-process non-blocking IO architecture, blocking CPU calculations will block everyone.

Big deal. Use workers to solve that. End of story.

would you mind giving an example of how you would code it so that that 1 request didn't block the rest?

in a browser I'd go with a setTimeout or setInterval hack to "fork" another thread. is this the same in node?

In Node Web Development [Packt], the author uses a Fibonacci algorithm as an example that could block the event loop.

It outlines one solution where the calculation is split into callbacks dispatched through the event loop, making use of process.nextTick()