我见过很多文章/博客说与传统的Java IO相比,Java NIO是一个更好的解决方案。
但今天我的一位同事向我展示了这个博客http://mailinator.blogspot.com/2008/02/kill-myth-please-nio-is-not-faster-than.html。我想知道Java社区中是否有人做过与Java NIO性能相关的这种基准测试。
答案 0 :(得分:34)
NIO vs IO是一个非常有趣的话题要讨论。
根据我的经验,这两种工具是两种不同的工具,用于两种不同的工作。我听说IO被称为“每个客户的线程”方法,而NIO被称为“所有客户的一个线程”方法,我发现这些名称虽然不是100%准确,但还不够合适。
正如我所看到的,NIO和IO的真正问题在于可扩展性。
NIO网络层将(应该?)使用单个线程来处理选择器并将读/写/接受作业分派给其他线程。这允许处理选择器的线程(“选择器线程”)除此之外什么都不做。这样可以在处理大量客户(请注意缺少实际数量)时更快地响应。现在,NIO开始崩溃的地方是服务器获得如此多的读/写/接受,以便选择器线程不断工作。过去这个和服务器的任何其他工作都开始滞后。此外,由于所有读/写/接受作业都由选择器线程处理,因此在混合中添加额外的CPU不会提高性能。
IO网络层可能会采用每个套接字1个线程的方法,包括监听套接字。因此线程数与客户端数量成正比。在适量的客户下,这种方法非常有效。通过使用这种方法支付的成本以线程成本的形式出现。如果您有2000个客户端连接到服务器...您至少有2001个线程。即使在四芯片中,每个芯片机器有6个内核,你只需要24个处理节点(如果算上超线程就可以有48个)来处理这些2001线程。实例化所有这些线程需要花费cpu time和ram,但即使你使用线程池,你仍然需要支付CPU上下文切换的成本,因为它们在线程之间移动。这可能会在高服务器负载下变得非常难看,如果编码不正确,可能会使整个机器停止运行。从好的方面来说,在这种情况下,将CPU添加到机器将改善性能。
现在一切都很好,但是很抽象,因为我的描述中没有数字可以帮助决定使用IO或NIO。这是因为还有更多变量需要考虑:
只是一些值得思考的东西。要回答哪个问题更快,NIO或IO:两者兼而有之:)
答案 1 :(得分:18)
比 B 更快经常一个非常简单的视图,有时明显错误。
NIO 不自动比普通IO快。
使用NIO,某些操作可能更快,您可以使用NIO轻松扩展到许多网络连接(因为每个连接不需要一个线程)。 / p>
但NIO不是一个神奇的“让事情变得更快” - 需要应用于所有事物的开关。
答案 2 :(得分:10)
使用NIO不是因为它 更快 ,而是因为它具有更好的 可扩展性 ,尤其是有大量的客户端
IO(阻塞IO /流IO)通常每个连接一个线程,以便更好地响应客户端。假设您使用单线程为所有客户端(阻止)监听/(阻止)读取/处理/(阻止)写入,就像星巴克在一个窗口中为所有客户服务一样,星巴克客户(您的客户)会不耐烦(超时)。
请注意,您可以考虑使用线程池来避免大量线程拖拽您的服务器。虽然它就像星巴克将所有客户分成几个窗口,但客户仍因其他人的阻止而延迟。这就是为什么每个连接一个线程是传统java IO编程的好选择。
NIO(无阻塞IO /块IO which one to use)使用Reactor Pattern来处理IO事件。在这种情况下,您可以使用单线程来阻止/监听|读取|处理|写入。然后阻塞(等待期)的客户端不会相互影响。
请注意,IO和NIO都可以使用多线程来利用更多的cpu资源,更多详细信息请参见Doug lee's introduction。
答案 3 :(得分:4)
你引用的文章是三岁。它使用Java 1.4.2(4)。
此后,Java 5,6和现在的7已经出局。
JVM和类库内部的巨大变化使得与1.4.2基准测试无关的任何事情都无关紧要。
如果你开始挖掘,你还会注意到java.io和java.nio之间的区别并不是那么清楚。许多java.io调用现在解析为java.nio类。
但是无论何时你想要提高性能,解决方案都不是做任何事情。确切知道的唯一方法是尝试不同的技术并测量它们,因为我的应用程序的速度对于您的应用程序来说并不一定如此,反之亦然。某些应用程序的NIO可能会慢一些。或者它可能是性能问题的解决方案。最有可能的是,它们都是两者兼而有之。
答案 4 :(得分:4)
该文章的问题在于它将阻塞IO与非阻塞NIO进行比较。在我自己的测试中,比较阻塞IO与阻塞NIO(更喜欢类似),NIO的速度提高了30%。
然而,除非你的应用程序是微不足道的,比如代理服务器,否则它不太重要。应用程序的作用更为重要。 IO和NIO都经过了多达10,000个连接的测试。
如果您想要超快速IO,可以使用Infiniband的Asynch IO(Java 7+)(不便宜,但延迟更低)
答案 5 :(得分:2)
此外,AFAIK,Java IO被重写为使用NIO(并且NIO具有更多功能)。微型计划只是一个坏主意,特别是当他们年老时,就像拉维尼奥所说的那样。
答案 6 :(得分:1)
Java NIO被认为比常规IO更快,因为:
Java NIO支持非阻塞模式。非阻塞IO比阻塞IO更快,因为它不需要每个连接一个专用线程。当您需要处理大量并发连接时,这可以显着提高可伸缩性,因为线程的扩展性不是很高。
Java NIO通过支持直接内存缓冲区来减少数据复制。可以读取和写入NIO套接字而无需任何数据复制。对于传统的Java IO,数据在套接字缓冲区和字节数组之间被多次复制。
答案 7 :(得分:1)
Java NIO和reactor模式本身并不太关乎网络性能,而是关于单线程模型在性能和简单性方面可以为系统提供的优势。而且,单线程方法可以带来显着的改进。看看这里:Inter-socket communication with less than 2 microseconds latency
答案 8 :(得分:0)
没有一个固有的原因,为什么一个比另一个更快。
每个线程的单连接模型目前正遭受Java线程具有大量内存开销的事实 - 线程堆栈被预先分配到固定(和大)的大小。这可以而且应该是固定的;然后我们可以廉价地创建数十万个线程。
答案 9 :(得分:-1)
Java IO包含了几个构造和类。你无法在这样的一般水平上进行比较。具体来说,NIO使用内存映射文件进行读取 - 理论上预计这比简单的BufferedInputStream
文件读取速度略快。但是,如果您比较RandomAccess
文件读取的内容,那么NIO内存映射文件将更快批次。