Gra*_*ham 8 java multithreading nio pthreads
我记得2或3年前阅读过几篇文章,其中人们声称现代线程库变得如此之好,以至于每个请求线程的服务器不仅比非阻塞服务器更容易编写,而且它们也更快.我相信这甚至在Java中通过将Java线程映射到pthreads的JVM进行了演示(即Java nio开销不仅仅是上下文切换开销).
但现在我看到所有"尖端"服务器都使用异步库(Java nio,epoll,甚至node.js).这是否意味着async赢了?
不是我认为的.如果两个模型都得到很好的实施(这是一个很大的要求),我认为NIO的概念应该占上风.
计算机的核心是核心.无论你做什么,你都不能比你的核心更多地并行化你的应用程序.即如果你有一台4核机器,你一次只能做4件事(我在这里略过一些细节,但这足以说明这个论点).
扩展这个想法,如果你有比核心更多的线程,你就浪费了.这种浪费有两种形式.首先是额外线程本身的开销.其次是在线程之间切换所花费的时间.两者都可能很小,但它们都存在.
理想情况下,每个核心只有一个线程,并且每个线程在其核心上以100%的处理速度运行.在理想情况下不会发生任务切换.当然还有操作系统,但如果您使用16核心机器并为操作系统留下2-3个线程,那么剩余的13-14将转向您的应用程序.这些线程可以切换他们在您的应用程序中执行的操作,例如当他们被IO要求阻止时,但不必在操作系统级别支付该成本.将其写入您的应用程序.
在SEDA http://www.eecs.harvard.edu/~mdw/proj/seda/中可以看到这种扩展的一个很好的例子.它显示了比标准的每个请求线程模型更好的负载扩展.
我的个人经历是Netty.我有一个简单的应用程序.我在Tomcat和Netty中都很好地实现了它.然后我加载100次并发请求(我认为超过800).最终,Tomcat逐渐减速并表现出非常突发/迟滞的行为.虽然Netty的实施只是增加了响应时间,但仍以令人难以置信的整体吞吐量继续.
请注意,这取决于可靠的实施.随着时间的推移,NIO仍在不断发展.我们正在学习如何调整我们的服务器操作系统以更好地使用它以及如何实现JVM以更好地利用操作系统功能.我不认为胜利者可以宣布,但我相信NIO将成为最终的赢家,并且它已经做得很好.
只要有足够的内存,它就会更快.
当连接太多,大多数都是空闲时,NIO可以保存线程,从而节省内存,系统可以处理比每个连接线程模型更多的用户.
CPU不是这里的直接因素.使用NIO,您实际上需要自己实现一个线程模型,这不可能比JVM的线程更快.
在任何一种选择中,记忆都是最终的瓶颈.当负载增加并且使用的内存接近最大时,GC将非常繁忙,并且系统经常显示100%CPU的症状.