问题 在Java中快速擦除(不清楚)ByteBuffer


我想“清理”一个 ByteBuffer 全部为零字节(全部 0x00)。我试图遍历缓冲区中的所有位置并将它们设置为 0x00但效率很差。有没有更好的方法来快速清除 ByteBuffer  - 类似于什么 BitSet.clear() 呢?

请注意 ByteBuffer.clear() 在这种情况下,对我来说不是一个合适的解决方案 - 我必须擦除缓冲区内的所有数据,而不是仅仅将指针重置为开头。

任何提示?

编辑:ByteBuffer用作哈希表的一部分,它维护哈希表条目的引用。每次需要刷新哈希表时,我都必须重置哈希表条目以便以后的哈希表插入。由于以随机方式访问哈希表,我不能简单地清除()字节缓冲区的状态。


11966
2018-06-25 21:51


起源

你能更详细地解释用例吗?你从什么中得到bytebuffer? - jontro
为什么你认为你需要将缓冲区归零? - user207421
它是直接缓冲区吗?如果没有,那么就是这样 ByteBuffer.wrap(new byte[123456]); - Greg Kopff
@GregKopff我想尽可能地消除对象创建,所以我更喜欢重用ByteBuffer而不是包装新的。 - asksw0rder
@jontro添加了关于ByteBuffer的更多信息〜 - asksw0rder


答案:


你有没有尝试过使用其中一个 ByteBuffer.put(byte[]) 要么 ByteBuffer.put(ByteBuffer) 一次写多个零的方法?然后,您可以使用预填充零的数组或缓冲区,以100或1000字节或其他任何方式迭代缓冲区。

缺点:这是一个可选操作,因此并非所有ByteBuffer实现都需要提供它...


6
2018-06-25 21:52



会尝试一下。希望批量放置会比循环好... thx! - asksw0rder
很抱歉这个迟到的回复,但这种方法确实可以减少刷新开销。我已经看到冲洗时间从~60ms减少到~2ms。会看看它是否足够好。 - asksw0rder


对于 ByteBuffer 提供可选的实现 array() 方法(其中 hasArray() 回报 true),你可以使用这个方法获取对底层数组的引用,然后使用 java.util.Arrays#fill()


4
2018-06-25 23:19





如果在刷新哈希表后需要一个新的干净的零填充ByteBuffer,最简单的方法是忘记现有的ByteBufefr并分配一个新的。官方文档没有这么说,但是所有已知的实现都将新缓冲区的内存归零。看到 http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6535542 了解更多信息。


1
2017-08-30 07:02





正如DNA提到的那样,有一个预先填充的缓冲液并使用 ByteBuffer.put(ByteBuffer) 可能是最快的便携式方式。如果那不实用,你可以做这样的事情来利用其中任何一个 Arrays.fill 要么 Unsafe.putLong 当适用:

public static void fill(ByteBuffer buf, byte b) {
    if (buf.hasArray()) {
        final int offset = buf.arrayOffset();
        Arrays.fill(buf.array(), offset + buf.position(), offset + buf.limit(), b);
        buf.position(buf.limit());
    } else {
        int remaining = buf.remaining();
        if (UNALIGNED_ACCESS) {
            final int i = (b << 24) | (b << 16) | (b << 8) | b;
            final long l = ((long) i << 32) | i;
            while (remaining >= 8) {
                buf.putLong(l);
                remaining -= 8;
            }
        }
        while (remaining-- > 0) {
            buf.put(b);
        }
    }
}

设置 UNALIGNED_ACCESS 需要一些关于JRE实现和平台的知识。以下是我在使用JNA(它提供的)时为Oracle JRE设置它的方法 Platform.ARCH 作为一种方便,规范的方式来访问 os.arch 系统属性)。

/**
 * Indicates whether the ByteBuffer implementation likely supports unaligned
 * access of multi-byte values on the current platform.
 */
private static final boolean UNALIGNED_ACCESS = Platform.ARCH.startsWith("x86");

1
2018-03-12 22:16