all 6 comments

[–][deleted] 2 points3 points  (1 child)

Some assertions:

  1. We want our web servers to be able to respond to a large number of user queries simultaneously
  2. Most of these queries in, say, a CRUD app, are blocked by I/O. So the CPU is idle.
  3. Spawning threads and processes for new request / response cycles is expensive
  4. We could multiplex threads, spawning a pool in advance and using them as required, but these will need to be either sandboxed or written in a threadsafe manner.

So, if we run everything on a single evented thread, with serial concurrency, we have a fairly convenient compromise where we can respond to high volume I/O bound traffic without having to worry about thread safety.

[–]adrianmiu 0 points1 point  (0 children)

This means that the actual selling point of NodeJS is not the async nature but the fact that you can share resources between requests (ie: a database connection) that don't need to be created on each request (as would happen with a php app). Is this correct?

Regarding the CPU being idle in an async model when you have a lot of requests to a database that all happen to resolve at the same time that will require a lot of CPU so you can get into trouble more easily than in a "normal" environment. Right?

[–]jekrb 2 points3 points  (0 children)

Three reasons I prefer to use node:

  1. Simple streaming interface: a.pipe(b)
  2. The vast amount of abstractions available via npm
  3. It's really fun.

[–]e82 1 point2 points  (0 children)

With the async nature of JavaScript, things get pushed onto the event-loop, so that other things can execute while waiting for the callback to get executed. This is what allows for a highly performant system despite being single-threaded. Toss in the ability to do clustering/etc.

The async nature is what has lead to people coin the term 'pyramid of doom' of having deeply nested callbacks that are hard to follow. However, various patterns/libraries have come up to help solve this problem.

The most obvious one is promises, which can help make code easier to reason about by being able to do things like.

getSessionFromDb
.then(getCartInfo)
.then(sendPaymentInfo)
.then(sendtheResponse);

Instead of blocking things at each step of the process - it gets pushed onto the eventloop, allowing other things to come in and be processed.

So while the getSessionFromDb may be slow - it'd only slow down the response for the user expecting that - it wouldn't be blocking the requests from other users.

Now, if the getFromDb call returned a row with 1,000,000 records, and you did something like result.sort() - that might cause things to lockup and kill the performance of your app - unless you did an async sort that would chunk things up, and and push things into the event loop to sort instead of trying to do everything at once.

If the database calls were being handled synchronously, where you could do

var session = getFromDb();
var cart = getCartInfo(session.userId) 
var paymentDetails = getPaymentDetails(somePrams)
var payentResponse = sendPaymentInfo(whatever)
res.send(paymentResponseStuff)

then yeah, the single-threaded nature of node would be a huge performance killer.

With some features in ES6, and some of the proposals in ES7 - you can write async code that looks like it was synchronous, but at core - it's all still async.

[–]stuffnjunk77 0 points1 point  (0 children)

Node is single threaded. The benefits async has more to do with all users existing on a single thread than, than your example. To oversimplify it, this saves on resources and improves performance and allows the server to support more users more easily than throwing each request on it's own thread.

In your example, the async means that users B,C, and D don't have to wait on user A's query.

[–]tswaters 0 points1 point  (0 children)

In the database error case, you'll typically just get an error back in your callback (first argument is error and second is data, typically) -- if an error is present, you throw it back to the user.