Hello Harry, replies inline. On Wed, Mar 23, 2016 at 5:25 PM, Harry Simons <simonsha...@gmail.com> wrote: > Hello, > > > I have not been able to see the following points addressed in all the online > material I have read to date on Node, and so, hope to be enlightened by some > very smart and knowledegable folks here that I presume would be reading > this. > > > 1. Since I/O happens asynchronously in worker threads, it is possible for a > single Node process to quickly/efficiently accept 1000s of incoming requests > compared to something like Apache. But, surely, the outgoing responses for > each of those requests will take their own time, won't it? For example, if > an isolated and primarily an I/O bound request takes, say, 3 seconds to get > serviced (with no other load on the system), then if concurrently hit with > 5000 such requests, won't Node take a lot of time to service them all, > fully? If this 3-second task happens to involve exclusive access to the > disk, then it would take 5000 x 3 sec = 15000 seconds, or over 4 hours of > wait to see the response for the last request coming out of the Node app. In > such scenarios, would it be correct to claim that a single-process Node > configuration can 'handle' 1000s of requests per second (granted, a > thread-server like Apache would do a lot worse with 5000 threads) when all > that Node may be doing is simply putting the requests 'on hold' till they > get fully serviced instead of rejecting them outrightly on initial their > arrival itself? I'm asking this because as I'm reading up on Node, I'm often > hearing how Node can address the C10K problem without any co-mention of any > specific application setups or any specific application types that Node can > or cannot handle... other than the broad, CPU- vs I/O-bound type of > application classification.
Node.js uses non-blocking I/O when it can and only falls back to a thread pool when it must. Sockets, pipes, etc. are handled in asynchronous, non-blocking fashion using native system APIs but e.g. file I/O is offloaded to a thread pool. > 2. What about the context switching overhead of the workers in the > worker-thread pool? If C10K requests hit a Node-based application, won't the > workers in the worker-thread pool end up context-switching just as much as > the user threads in the thread pool of a regular, threaded-server (like > Apache)...? because, all that would have happened in Node's event thread > would be a quick request-parsing and request-routing, with the remainder > (or, the bulk) of the processing still happening in the worker thread? That > is, does it really matter (as far as minimization of thread > context-switching is concerned) whether a request/response is handled from > start to finish in a single thread (in the manner of threaded-server like > Apache), or whether it happens transparently in a Node-managed worker thread > with only minimal work (of request parsing and routing) subtracted from it? > Ignore here the simpler, single-threaded user model of coding that comes > with an evented server like Node. See above. Depending on the application, you may not hit the thread pool much or at all. > 3. If the RDBMS instance (say, MySQL) is co-located on the Node server box, > then would it be correct to classify a database CRUD operation as a pure I/O > task? My understanding is, a CRUD operation on a large, relational database > will typically involve heavyduty CPU- and I/O-processing, and not just > I/O-processing. However, the online material that I've been reading seem to > label a 'database call' as merely an 'I/O call' which supposedly makes your > application an I/O-bound application if that is the only the thing your > application is (mostly) doing. Communication with the database normally takes place over a TCP or UNIX socket, so as far as node.js is concerned, it's not much different from any other network connection. The heavy-duty number crunching takes place in a different process, the RDBMS. > 4. A final question (related to the above themes) that may require knowledge > of modern hardware and OS which I am not fully up-to-date on. Can I/O (on a > given I/O device) be done in parallel, or even concurrently if not > parallelly, and THUS, scale proportionally with user-count? Example: Suppose > I have written a file-serving Node app that serves files from the local > hard-disk, making it strongly an I/O-bound app. If hit with N (== ~ C10K) > concurrent file serving requests, what I think would happen is this: > > The event-loop would spawn N async file-read requests, and go idle. > (Alternatively, Node would have pre-spawned all its workers in the pool on > process startup.) > The N async file-read requests would each get assigned to N worker threads > in the worker thread pool. If N > pool size, then the balance will be made > to wait in some sort of an internal queue to get assigned to a worker. > Each file-read request would run concurrently at best, or sequentially at > worst - but definitely NOT N-parallelly. That is, even a RAID configuration > would be able to service merely a handful of file-read requests parallelly, > and certainly not all N parallelly. > This would result in a large, total wait-time for the last file serving > request to be served fully. That's by and large correct. > So, if all these 4 points are true, how could we really say that a single > Node-process based application is good for (because it scales well) for > I/O-bound applications? Can the mere ability to receive a large number of > incoming requests and keep them all on hold indefinitely while their I/O > fully completes (versus, rejecting them outrightly on their initial arrival > itself) be called 'servicing the requests'? Can such an application be seen > as scaling well with respect to user-count? For many applications the answer is 'yes' because they can break up the request in smaller parts that they can service independently. Say your application has to read a) a file from disk, b) query a database, and c) consult a web service before it can send a reply. In the traditional web server model, it takes a+b+c time, whereas with the asynchronous model it's max(a,b,c). max(a,b,c) <= a+b+c so worst case, it performs the same, but common case, it's much faster. Does that answer your questions? -- Job board: http://jobs.nodejs.org/ New group rules: https://gist.github.com/othiym23/9886289#file-moderation-policy-md Old group rules: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines --- You received this message because you are subscribed to the Google Groups "nodejs" group. To unsubscribe from this group and stop receiving emails from it, send an email to nodejs+unsubscr...@googlegroups.com. To post to this group, send email to nodejs@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/nodejs/CAHQurc9Ajsyn_OpzvL%3DYoNQ%3DGBm7zzyVKH7aoeZxzkRxzVBa9w%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.