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