Node.js 单线程 VS 传统 web 服务器线程池

Node.js single thread VS Tranditonal webserver thread pool

我是 node.js 的新手。我目前正在阅读 Basarat Ali Syed 的书,名为“Beignning Node.js”。

这里摘录一段,说明传统网络服务器线程池的缺点:

Most web servers used thread pool this method a few years back and many continue to use today. However, this method is not without drawbacks. Again there is wasting of RAM between threads. Also the OS needs to context switch between threads (even when they are idle), and this results in wasted CPU resources.

不太明白为什么线程池中的线程之间会有上下文切换。据我所知,一个线程将在任务期间持续。并且一旦任务完成,线程就会空闲去接收下一个任务。

所以我的Q1:为什么需要上下文切换?什么时候会发生线程间的上下文切换?

我的Q2:为什么node.js不使用多线程来处理事件队列中的事件?不是更高效,减少事件的排队时间吗?

上下文切换是当 OS 需要 运行 多于 CPU 核心的线程时。比如说你有 10 个线程。而且他们都很忙(这意味着 none 他们已经完成了他们的任务)。但是您的 CPU 只是一个双核 CPU (为简单起见,假设没有超线程)。那么,如何才能让10个线程都运行呢?不可能!!

答案是上下文切换。 OS,当有很多进程和线程要执行时,将为每个线程分配一定的时间给 运行。这段时间之后 OS 将切换到另一个线程,以便所有线程都有时间使用 CPU.

术语"context switch"指的是当OS需要将CPU给另一个thread/process时需要临时复制寄存器中的所有值到该线程的内存,否则另一个 process/thread 将在恢复时弄乱切换线程的计算。 OS 还需要重新指向虚拟内存表,以便两个进程不会弄乱彼此的内存。此操作的开销取决于 CPU 体系结构。像 Sparc 这样的一些架构针对上下文切换进行了优化。超线程是一种在硬件中实现上下文切换的功能,因此速度更快(但话又说回来,在 Intel/AMD64 架构上实现超线程时,每个 CPU 只能获得一个额外的上下文)。

不使用多线程完全避免了上下文切换。特别是如果您的程序是唯一的程序 运行ning。所以在单核上 CPU,非阻塞的单线程程序通常可以击败多线程程序。

然而,现在很难找到一个单核 CPU。您想要 运行 的理想线程数等于您拥有的内核数。这样做也可以避免上下文切换。但即便如此,让一个复杂的多线程程序快速 运行 并不容易。使非阻塞单线程程序快速 运行 更容易。在大多数 Web 应用程序中,多线程程序不会比非阻塞单线程程序有任何优势,因为它们都是 I/O 绑定的。

非阻塞单线程程序基本上是使用事件在用户空间中实现类似线程的行为。在支持使面向事件的编程看起来像多线程编程的语法的语言中,这有时被称为 "green threads"。