2012-06-25 3 views
10

Я пытаюсь «очистить» ByteBuffer, чтобы быть всеми нулевыми байтами (все 0x00). Я попытался перебрать все позиции в буфере и установить их на 0x00, но эффективность плохая. Есть ли лучший способ быстро очистить ByteBuffer - аналогично тому, что делает BitSet.clear()?Быстрая стирание (непонятно) a ByteBuffer в Java

Обратите внимание: ByteBuffer.clear() не подходит для меня в этом сценарии - мне нужно стереть все данные внутри буфера, а не просто сбросить указатель на начало.

Любые подсказки?

Редактировать: ByteBuffer используется как часть хэш-таблицы и поддерживает ссылки на записи хеш-таблицы. Каждый раз, когда хеш-таблицу нужно очищать, мне нужно сбросить записи хэш-таблицы для последующей вставки хэш-таблицы. Поскольку хэш-таблица получает доступ случайно, я не могу просто очистить() состояние байтового буфера.

+0

Не могли бы вы объяснить пример использования более подробно? Из чего вы получаете байтовый буффер? – jontro

+0

Почему вы думаете, что вам нужно обнулить буфер? – EJP

+0

Является ли это прямым буфером? Если нет, как насчет 'ByteBuffer.wrap (новый байт [123456]),' –

ответ

6

Вы пытались использовать один из методов ByteBuffer.put(byte[]) или ByteBuffer.put(ByteBuffer), чтобы написать несколько нулей за один раз? Затем вы можете перебирать буфер в кусках в 100 или 1000 байт или что угодно, используя массив или буфер, предварительно заполненный нулями.

Даунсайд: это дополнительная операция, поэтому не все реализации ByteBuffer обязаны обеспечить его ...

+0

Попробуем. Надеюсь, нагрузка на массу будет лучше, чем цикл ... THX! – asksw0rder

+2

Извините за этот поздний ответ, но этот подход действительно работает над уменьшением наводнений. Я видел, что время промывки уменьшилось с ~ 60 мс до ~ 2 мс. Увидит, достаточно ли это. – asksw0rder

4

Для ByteBuffer реализаций, которые обеспечивают дополнительный array() метод (где hasArray() возвращает true), вы можете использовать этот метод получает ссылку на базовый массив, затем используйте java.util.Arrays#fill().

1

Если вам нужен свежий чистый заполненный нулем ByteBuffer после того, как хеш-таблица покраснела, самый простой способ - забыть существующий ByteBufefr и выделить новый. Официальная документация не говорит об этом, но все известные реализации обнуляют память новых буферов. См. http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6535542 для получения дополнительной информации.

1

Как упоминает ДНК, наличие предварительно заполненного буфера и использование 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 и платформе. Вот как я бы установил его для Oracle JRE, когда также использовал JNA (который обеспечивает 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");