设置ByteBuffer顺序(取决于缓冲区使用)是否安全/良好的优化?

时间:2012-02-14 15:39:56

标签: java performance endianness bytebuffer

Java是Big-Endian;网络堆栈是Big-Endian; Intel/AMD(基本上所有的计算机)和ARM CPU(最常见的Android和iOS芯片)都是小端的。

鉴于所有这些,如果我为不同的用途分配直接的ByteBuffer,总是尝试匹配本机交互的字节序是一个好主意吗?

更具体地说:

  • 网络缓冲区:保留Big-Endian。
  • 文件缓冲区(在x86上):Little-Endian。
  • OpenGL / Native Process Buffer:Little-Endian。

依旧......

我问这个是因为我从未想过我的ByteBuffers的Endian-ness,但是在看到SO上的other questions和它可以拥有的performance impact后,它似乎值得或者至少在使用ByteBuffers时我应该更加注意的事情。

或者也许在这里有一个不道德的地方担心我会失踪并希望知道的尾数?

2 个答案:

答案 0 :(得分:2)

如果您正在使用ByteBuffer来读取和存储BYTES,那么字节顺序根本不重要,只需使用默认值。

如果您正在读写非字节基本类型(short,int,float,long,double),那么如果CPU的Endianness(ByteOrder.nativeOrder())与之不同,那么底层处理器将不得不做额外的工作。默认Java Big Endianness。如果您阅读了与您链接的其他SO问题,可以推断出原因......处理器必须翻转字节才能使用相关的基本类型进行任何操作。此字节翻转(交换)操作将耗尽一些CPU周期。

使用两个短值1和2的快速示例。假设您的CPU是x86处理器。

short A = 1;
short B = 2;
short C = A + B;

如果您的本机处理器需要小端

MOV ax, short[A] ; ax register [ 01, 00 ]
MOV bx, short[B] ; bx register [ 02, 00 ]
ADD ax, bx ; ax register [ 03, 00 ]
MOV short[C], ax ; C [ 03, 00 ]

你给它大端,它必须做额外的工作。

MOV ax, short[A] ; ax register [ 00, 01 ]
MOV bx, short[B] ; bx register [ 00, 02 ]
BSWAP ax ; ax register [ 01, 00 ]
BSWAP bx ; bx register [ 02, 00 ]
ADD ax, bx ; ax register [ 03, 00 ]
MOV short[C], ax ; C [ 03, 00 ]

因此,在最低级别上它很重要,但除非您注意/分析代码中的主要瓶颈,否则只需使用默认值。

答案 1 :(得分:2)

它在你引用的文章中指出差异非常小。 (可能没有)

所引用的结果并未显示出持续的改进,使用最新的JVM可能会缩小差距。


  • 当我启用“本机字节排序”时(如果机器使用不同的“endian”约定,这实际上是不安全的):
mmap: 1.358
bytebuffer: 0.922
regular i/o: 1.387
  • 当我注释掉order语句并使用默认的big-endian顺序时:
mmap: 1.336
bytebuffer: 1.62
regular i/o: 1.467

有一个测量的差异,但它在整体方案中很小。如果你想要它更快,我找到的唯一一个有很大区别的选择是直接使用Unsafe,在这种情况下只有本机排序可用。

即便如此,它只对大多数对延迟敏感的应用程序有所帮​​助。

使用代码和注释时,不安全更有趣。 ;)

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/sun/misc/Unsafe.java