2015-10-13 97 views
1

我是node.js的新手。我目前正在阅读这本名为'Beignning Node.js'由Basarat Ali SyedNode.js单线程VS Tranditonal网络服务器线程池

下面是从中摘录其中指出传统的Web服务器的线程池的缺点:使用线程池这个 方法在几年前,许多延用至今

大多数Web服务器。但是,这种方法不是没有缺点。在线程之间再次浪费RAM 。此外,操作系统需要在线程 (即使它们处于空闲状态)之间进行上下文切换,这会导致浪费CPU资源。

我不太明白为什么在线程池内的线程之间有上下文切换。据我所知,一个线程将在任务期间持续。一旦任务完成,线程将自由接收下一个任务。

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

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

回答

1

上下文切换是指操作系统需要运行更多的线程而不是CPU核心。比如说你有10个线程。他们都很忙(这意味着他们没有完成任务)。但是你的CPU只是一个双核CPU(为简单起见,不要假设超线程)。那么,所有10个线程如何运行呢?这是不可能的!!

答案是上下文切换。当OS提供大量进程和线程执行时,将为每个线程分配一定的时间以运行。在这段时间之后,操作系统将切换到另一个线程,以便所有线程都有一定的时间使用CPU。

术语“上下文切换”是指当操作系统需要将CPU提供给另一个线程/进程时,它需要将寄存器中的所有值临时复制到该线程的内存中,否则另一个进程/线程将会混乱重新开始计算切换后的线程。操作系统还需要重新定位虚拟内存表,以便两个进程不会混淆对方的内存。这种操作的成本有多高取决于CPU架构。一些像Sparc这样的体系结构针对上下文切换进行了优化。超线程是一种在硬件中实现上下文切换的功能,因此速度更快(但是,如果在Intel/AMD64架构上实现超线程,每个CPU只能获得一个额外上下文)。

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

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

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

+0

谢谢,slebetman,为您提供如此全面的答案。它确实有帮助。现在我可以理解人们为什么说node.js不能运行CPU消耗任务。这是因为node.js只有一个线程。没有上下文切换,它必须等待该任务在能够执行下一个任务之前完全查询。 –

+0

但是这对多线程系统来说不成问题。因为操作系统可以轻松地分配一定的时间来运行任务。如果其他紧急任务到来,OS可以执行上下文切换。紧急任务完成后,可以再次恢复前一个任务,而不会产生任何头痛。 –

+0

@ ShaohuaHuang:这里的关键洞察是上下文切换并不便宜。在事件循环中管理任务的单线程流程可轻松击败依赖于操作系统来管理任务的多线程流程。最惊人的例子之一是tclhttpd在21世纪初击败了Apache。 Tclhttpd是用一种非常慢的编程语言Tcl编写的,而Apache是​​用C编写的。然而Apache在服务静态文件方面速度较慢。关键的区别是Apache是​​多线程的,但tclhttpd是非阻塞的,单线程的。 – slebetman