What role plays the V8 engine in Node.js?
<p>In the past days I've been researching to understand how the Node.js event-based style can handle much more concurrent request than the classic multithreading approach. At the end is all about less memory footprint and context-switchs because Node.js only use a couple of threads (the V8 single thread and a bunch of C++ worker threads plus the main-thread of libuv).</p>

<p>But how can handle a huge number of requests with a few threads, because at the end some thread must be blocked waiting, for example, a database read operation.
I think that the idea is: instead of having both the client thread and the database thread blocked, that only the database thread be blocked and alert the client thread when it ends.</p>

<p>This is how I understand Node.js works.</p>

<p>I've been wondering what gives to Node.js the capability to handle HTTP requests.
Based on what I read until now, I understand that <a href="http://docs.libuv.org/en/v1.x/design.html" rel="nofollow noreferrer">libuv</a> is who does that work:</p>

<blockquote>
  <p>Handles represent long-lived objects capable of performing certain
  operations while active. Some examples: a prepare handle gets its
  callback called once every loop iteration when active, and <strong>a TCP
  server handle get its connection callback called every time there is a
  new connection.</strong></p>
</blockquote>

<p><a href="https://i.stack.imgur.com/VpqtP.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/VpqtP.png" alt="enter image description here"></a></p>

<p>So, the thread that is waiting incoming http request is the main-thread of libuv that executes the libuv event loop.</p>

<p>So when we write </p>

<pre><code>const http = require('http');

const hostname = '127.0.0.1';
const port = 1337;

http.createServer((req, res) =&gt; {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Hello World\n');
}).listen(port, hostname, () =&gt; {
  console.log(`Server running at http://${hostname}:${port}/`);
});
</code></pre>

<p>... I'm putting in the libuv a callback that will be executed in the V8 engine when a request comes in?</p>

<p>The order of the events will then be</p>

<ol>
<li>A TCP packet arrives </li>
<li>The OS creates an event and sends to the event loop</li>
<li>The event loop handles the event and creates a V8 event</li>
</ol>

<p>If I execute blocking code inside the anonymous function that handles the request I will be blocking the V8 thread.</p>

<p>In order to avoid this I need to execute non-blocking code that will be executed in another thread. I suppose this "another thread" is the main-thread of libuv where</p>

<blockquote>
  <p>network I/O is always performed in a single thread, each loop’s thread</p>
</blockquote>

<p>This thread will not block because uses OS syscalls that are async.</p>

<blockquote>
  <p>epoll on Linux, kqueue on OSX and other BSDs, event ports on SunOS
  and IOCP on Windows</p>
</blockquote>

<p>I also suppose that <a href="https://nodejs.org/dist/latest-v5.x/docs/api/http.html#http_http_request_options_callback" rel="nofollow noreferrer">http.request</a> is using libuv for achive this.</p>

<p>Similary, if I need to do some file I/O without blocking the V8 thread<br>
I will use the <a href="https://nodejs.org/dist/latest-v5.x/docs/api/fs.html" rel="nofollow noreferrer">FileSystem</a> module of Node. This time the libuv main thread can't handle this in a non-blocking way because the OS doesn't offer this feature.</p>

<blockquote>
  <p>Unlike network I/O, there are no platform-specific file I/O primitives
  libuv could rely on, so the current approach is to run blocking file
  I/O operations in a thread pool.</p>
</blockquote>

<p>In this case a classic thread pool is needed in order to not block the libuv event-loop.</p>

<p>Now, if I need to query a database all the responsability of not block either the V8 thread and the libuv thread is in hands of the driver developer.
If the driver doesn't use the libuv it will block the V8 engine.</p>

<p>Instead, if it uses the libuv but the underlying database doesn't have async capabilities, then it will <a href="https://www.future-processing.pl/blog/on-problems-with-threads-in-node-js/" rel="nofollow noreferrer">block a worker thread</a>.</p>

<p>Finally, if the database gives async capabilities it will only block the database thread. (In this case I could avoid libuv at all and call the driver directly from the V8 thread)</p>

<p>If this conclusions describes correctly, although in a simplistic way, the ways that libuv and the V8 works together in Node.js, I can't see the benefits of use V8 because we could do all the work in libuv directly (unless the objective is to give the developer a language that allows write an event-based code in a simpler way).</p>