Java ByteBuffer 放置与包装

Posted

技术标签:

【中文标题】Java ByteBuffer 放置与包装【英文标题】:Java ByteBuffer put vs wrap 【发布时间】:2012-06-19 08:26:51 【问题描述】:

用 Java 填充预先分配的 ByteBuffer 的最快方法是什么?

我首先用allocateDirect() 设置字节缓冲区的大小,这只需要做一次。之后,我需要以byte[] 数组的形式尽可能快地连续填充它(回收它),大约每 5ms 一次,并且不占用内存,因为我已经预先分配了字节缓冲区。 目前,我使用put() 指令,在我的系统中完成该指令大约需要 100 毫秒。 是否有另一种方法来填充字节缓冲区? wrap() 函数在不重新分配数组的情况下运行得更快吗?

【问题讨论】:

你可以试试 System.arraycopy。检查:Is it better to use System.arraycopy(…) than a for loop for copying arrays? 【参考方案1】:

我希望你的意思是 byte[] 而不是 Byte[]

put() 是将 byte[] 复制到 ByteBuffer 的最快方法。一种更快的方法是首先写入ByteBuffer,而根本不使用byte[]

如果复制需要 100 毫秒,则可能是您复制了太多数据。在此测试中,它会在 128 微秒内复制 1 MB。

ByteBuffer bb = ByteBuffer.allocateDirect(1024 * 1024);
byte[] bytes = new byte[bb.capacity()];

int runs = 50000;
long start = System.nanoTime();
for (int i = 0; i < runs; i++) 
    bb.clear();
    bb.put(bytes);

long time = System.nanoTime() - start;
System.out.printf("Average time to copy 1 MB was %.1f us%n", time / runs / 1e3);

打印

Average time to copy 1 MB was 128.9 us

【讨论】:

糟糕,我的意思是字节 []。因此,持续填充 ByteBuffer 的唯一方法(可能是最快的方法)是使用“.put(...)”?我必须在每个周期中填写的数据,就像你的测试一样,大约 1MB,我无法绕过或减少。 你确定它是 100 毫秒而不是 100 微秒吗?如果你不能减少它,最好的解决方案是根本不使用 byte[] 并将产生这种写入的东西直接写入 ByteBuffer。 是的,大约需要 100 毫秒。不幸的是,我从硬件回调中获得的数据以 byte[] 数组的形式到达,需要处理它的最终指令只接受一个 ByteBuffer,我也无法更改。所以我必须找到最快的方法来复制这些数据,而不是一直重新分配内存。 您能否运行我的测试,因为 1 MB 上的 put() 不可能花费 100 毫秒?它应该更接近 0.1 毫秒。 答案很好,我喜欢你提供 ByteBuffer.put() 速度的测试代码.. 但实际上它没有提供任何关于ByteBuffer.wrap().. 速度的信息.你说put()是最快的方法,但实际上你还需要考虑ByteBuffer对象的创建...ByteBuffer.wrap()复制字节并同时实例化一个ByteBuffer..你确定这是比实例化 ByteBuffer 然后使用 put() 复制字节慢?还是你通常只使用一个 ByteBuffer 对象来完成多个字节复制任务?【参考方案2】:

wrap 应该更快,因为——如果我正确理解了文档——它不会复制字节数组,而只是设置成员变量(容量/限制/位置)。 当然,如果您已经从某个地方获得了带有所需数据的 byte[],那么 wrap 才有意义。

【讨论】:

以上是关于Java ByteBuffer 放置与包装的主要内容,如果未能解决你的问题,请参考以下文章

java中怎么在客户端与服务器之间以bytes(ByteBuffer)的方式拷贝二进制文件?

I/O:ByteBuffer

Java:从 ByteBuffer 扩展

在 Java 中将 ByteBuffer 转换为字符串

将异常的堆栈跟踪转换为 byte[] 数组或 ByteBuffer (Java) 是不是更有效?

JNI从ByteBuffer获取数据,返回byte[]