【问题标题】:Fast erase (not clear) a ByteBuffer in Java快速擦除(不清除)Java 中的 ByteBuffer
【发布时间】:2012-06-27 05:06:10
【问题描述】:

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

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

有什么提示吗?

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

【问题讨论】:

  • 你能更详细地解释一下这个用例吗?你从哪里得到字节缓冲区?
  • 您认为为什么需要将缓冲区归零?
  • 是直接缓冲吗?如果没有,那么 ByteBuffer.wrap(new byte[123456]);
  • @GregKopff 我想尽可能地消除对象创建,所以我更喜欢重用 ByteBuffer 而不是包装一个新的。
  • @jontro 添加了更多关于 ByteBuffer 的信息~

标签: java bytebuffer erase


【解决方案1】:

您是否尝试过使用ByteBuffer.put(byte[])ByteBuffer.put(ByteBuffer) 方法之一一次性写入多个零?然后,您可以使用预先填充零的数组或缓冲区,以 100 或 1000 字节的块或其他任何大小对缓冲区进行迭代。

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

【讨论】:

  • 会试一试。希望批量放置会比循环更好...谢谢!
  • 很抱歉回复晚了,但这种方法确实可以减少刷新开销。我已经看到冲洗时间从 ~60ms 减少到 ~2ms。看看是否足够好。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      正如 DNA 所提到的,预先填充缓冲液并使用 ByteBuffer.put(ByteBuffer) 可能是最快的便携方式。如果这不切实际,您可以执行以下操作以利用 Arrays.fillUnsafe.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");
      

      【讨论】:

        猜你喜欢
        • 2016-09-16
        • 2013-05-01
        • 2018-01-24
        • 2015-08-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多