我担心我在这里“做错了事”,如果是这样,请删除我并道歉。特别是,我看不到我是如何创建一些人创建的整洁的小注释的。但是,我对这个线程有很多担忧/观察。
1) 流行答案之一的伪代码中的注释元素
result = query( "select smurfs from some_mushroom" );
// twiddle fingers
go_do_something_with_result( result );
本质上是假的。如果线程正在计算,那么它不是在摆弄拇指,而是在做必要的工作。另一方面,如果它只是在等待 IO 的完成,那么它并没有使用 CPU 时间,内核中线程控制基础结构的全部意义在于 CPU 会找到一些有用的事情去做。正如这里所建议的那样,“摆弄你的拇指”的唯一方法是创建一个轮询循环,并且没有人编写过真正的网络服务器,没有人能够做到这一点。
2)“线程很难”,只有在数据共享的上下文中才有意义。如果您有本质上独立的线程,例如处理独立的 Web 请求时的情况,那么线程化非常简单,您只需编写如何处理一项工作的线性流程,然后坐下来就知道它将处理多个请求,并且每个将有效地独立。就我个人而言,我敢说,对于大多数程序员来说,学习闭包/回调机制比简单地编写自上而下的线程版本要复杂得多。(但是,是的,如果你必须在线程之间进行通信,生活会变得非常艰难,但我不相信闭包/回调机制真的改变了这一点,它只是限制了你的选择,因为这种方法仍然可以通过线程实现. 无论如何,那个'
3) 到目前为止,没有人提出任何真实的证据来说明为什么一种特定类型的上下文切换会比任何其他类型更耗时或更短。我在创建多任务内核方面的经验(嵌入式控制器的小规模,没有什么比“真正的”操作系统更花哨)表明情况并非如此。
4) 迄今为止,我所看到的所有插图都旨在表明 Node 比其他网络服务器快多少,但它们存在严重缺陷,但它们确实间接地说明了我肯定会接受 Node 的一个优势(和这绝不是微不足道的)。Node 看起来不需要(实际上甚至不允许)调整。如果您有线程模型,则需要创建足够的线程来处理预期的负载。做得不好,最终会导致性能不佳。如果线程太少,那么CPU是空闲的,但是无法接受更多的请求,创建的线程太多,会浪费内核内存,而在Java环境下,也会浪费主堆内存. 现在,对于 Java,浪费堆是破坏系统性能的第一个也是最好的方法,因为高效的垃圾收集(目前,这可能会随着 G1 的变化而改变,但至少在 2013 年初,陪审团似乎仍然在这一点上)取决于有大量的备用堆。所以,有一个问题,用太少的线程来调整它,你有空闲的 CPU 和低吞吐量,用太多来调整它,它会以其他方式陷入困境。
5) 还有另一种方式,我接受 Node 的方法“设计速度更快”这一说法的逻辑,就是这样。大多数线程模型使用时间切片上下文切换模型,分层在更合适(value判断警报:)和更高效(不是value判断)的抢占模型之上。发生这种情况有两个原因,第一,大多数程序员似乎不理解优先级抢占,第二,如果你在 windows 环境中学习线程,无论你喜欢与否,时间片都在那里(当然,这加强了第一点; 值得注意的是,Java 的第一个版本在 Solaris 实现中使用了优先级抢占,在 Windows 中使用了时间片。因为大多数程序员不理解并抱怨“线程在 Solaris 中不起作用” 他们到处都将模型更改为时间片)。无论如何,底线是时间切片会创建额外的(并且可能是不必要的)上下文切换。每次上下文切换都会占用 CPU 时间,而这些时间会从手头实际工作中可以完成的工作中有效地消除。但是,由于时间切片而在上下文切换上所花费的时间量不应超过总时间的很小一部分,除非发生了非常奇怪的事情,而且我没有理由认为情况会如此简单的网络服务器)。所以,是的,时间片中涉及的过多上下文切换是低效的(这些不会发生在 并且从手头的实际工作中可以完成的工作有效地消除了时间。但是,由于时间切片而在上下文切换上所花费的时间量不应超过总时间的很小一部分,除非发生了非常奇怪的事情,而且我没有理由认为情况会如此简单的网络服务器)。所以,是的,时间片中涉及的过多上下文切换是低效的(这些不会发生在 并且从手头的实际工作中可以完成的工作有效地消除了时间。但是,由于时间切片而在上下文切换上所花费的时间量不应超过总时间的很小一部分,除非发生了非常奇怪的事情,而且我没有理由认为情况会如此简单的网络服务器)。所以,是的,时间片中涉及的过多上下文切换是低效的(这些不会发生在内核线程作为一项规则,顺便说一句),但差异将是吞吐量的百分之几,而不是通常隐含在 Node.js 中的性能声明中隐含的那种整数因素。
无论如何,为所有冗长而漫不经心的事情道歉,但我真的觉得到目前为止,讨论还没有证明任何事情,我很高兴听到有人在这两种情况下的意见:
a) 对为什么 Node 应该更好的真正解释(除了我上面概述的两个场景,我认为第一个(调整不佳)是迄今为止我看到的所有测试的真实解释。([编辑] ], 实际上, 我越想, 我就越想知道这里大量堆栈使用的内存是否很重要. 现代线程的默认堆栈大小往往非常大, 但由 a 分配的内存基于闭包的事件系统只是需要的)
b) 一个真正的基准测试,它实际上为选择的线程服务器提供了公平的机会。至少那样,我不得不停止相信这些声明本质上是错误的;>([编辑]这可能比我预期的要强得多,但我确实觉得对性能优势的解释充其量是不完整的,并且显示的基准是不合理的)。
干杯,托比