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

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


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

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

直接缓冲区具有许多优点

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

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

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

[实时] [选择器]

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

当您只是复制数据时,直接缓冲区是最好的,比如从套接字到文件, 反之亦然,因为数据不必遍历JNI / Java边界,它只停留在JNI域。 如果您打算自己查看数据,那么直接缓冲区就没有意义了。