我何时应该使用Java NIO的直接缓冲区进行网络I/O的简单规则?

Joh*_*ine 9 java nio bytebuffer real-time css-selectors

有天赋的人可以用简单直接的方式解释复杂的事情来解决这个问题吗?要在使用Java NIO进行网络I/O时,何时使用直接ByteBuffers与常规ByteBuffers,以获得最佳性能?


例如:我应该读入堆缓冲区并从那里解析它,执行许多get()(逐字节)或者我应该将它读入直接缓冲区并从直接缓冲区解析?

Pet*_*rey 11

要在使用Java NIO进行网络I/O时,何时使用直接ByteBuffers与常规ByteBuffers,以获得最佳性能?

直接缓冲区具有许多优点

  • 避免在Java和本机内存之间传递的额外数据副本.
  • 如果重复使用它们,则只使用的页面变为实际内存.这意味着你可以使它们比我们需要的大得多,它们只会浪费虚拟内存.
  • 您可以有效地以本机字节顺序访问多字节基元.(基本上是一个机器代码指令)

我应该读入堆缓冲区并从那里解析它,做多个get()(逐字节)或者我应该将它读入直接缓冲区并从直接缓冲区解析?

如果你一次读一个字节,你可能没有太大的优势.但是,使用直接字节缓冲区,您可以一次读取2个或4个字节,并有效地一次解析多个字节.

[实时] [选择器]

如果要解析实时数据,我会避免使用选择器.我发现使用阻塞NIO或繁忙等待NIO可以为您提供最低延迟性能(假设您的连接数量相对较少,例如最多20个)

  • 你可以做`while((len = socketChannel.read(byteBuffer))<1);`或者轮询一个socketChannels数组.您不需要选择器.;) (2认同)

use*_*421 5

当您只是将数据复制(例如从套接字复制到文件,反之亦然)时,直接缓冲区是最好的选择因为数据不必遍历JNI / Java边界,它只停留在JNI范围内。如果您打算自己查看数据,则直接缓冲区没有意义。

  • 是否使用JNI是特定于实现的。AFAIK Android使用本地JNI调用,直接ByteBuffer较慢。HotSpot和OpenJDK将其视为内在函数,因此无需JNI即可使直接ByteBuffer更快。 (2认同)