2012-06-25 76 views
10

ByteBufferをすべてクリーンアップしようとしています(すべて0x00)。私はバッファ内のすべての位置をループし、それらを0x00に設定しようとしましたが、効率が悪いです。 ByteBufferをすばやくクリアする良い方法はありますか?BitSet.clear()と似ていますか?JavaのByteBufferを高速消去(クリアではない)

このシナリオでは、ByteBuffer.clear()は私にとっては適切な解決策ではないことに注意してください。ポインタを先頭にリセットするだけでなく、バ​​ッファ内のすべてのデータを消去する必要があります。

ヒント

編集:ByteBufferはハッシュテーブルの一部として使用され、ハッシュテーブルエントリの参照を保持します。ハッシュテーブルをフラッシュする必要があるたびに、後でハッシュテーブルを挿入するためにハッシュテーブルのエントリをリセットする必要があります。ハッシュテーブルはランダムにアクセスされるので、単にバイトバッファの状態をクリア()することはできません。

+0

このユースケースについてもう少し詳しく説明できますか?あなたはバイトバッファを何から得ますか? – jontro

+0

なぜバッファをゼロにする必要があると思いますか? – EJP

+0

ダイレクトバッファーですか?そうでなければ、ByteBuffer.wrap(new byte [123456]); ' –

答えて

6

ByteBuffer.put(byte[])またはByteBuffer.put(ByteBuffer)のいずれかの方法を使用して、1回で複数のゼロを書き込もうとしましたか?その後、100または1000バイトのチャンクでバッファを繰り返し処理することができます。また、配列またはバッファにゼロがあらかじめ埋め込まれています。

ダウンサイド:これは、オプションの操作ですので、のByteBufferのすべての実装は、それを提供するために必要とされていない...オプションarray()方法(hasArray()戻りtrue)を提供ByteBuffer実装で

+0

それを試してみましょう。うまくいけば、バルクはループよりも良いでしょう... thx! – asksw0rder

+2

この後半の返事は申し訳ありませんが、このアプローチは実際にはフラッシングオーバーヘッドを減らすために機能します。私はフラッシング時間が〜60msから〜2msに減少したのを見ました。それが十分であるかどうかを確認します。 – asksw0rder

4

、あなたがこれを使用することができますメソッドが基になる配列への参照を取得した後、java.util.Arrays#fill()を使用します。

1

ハッシュテーブルがフラッシュされた後に、きれいなゼロで埋められたByteBufferが必要な場合、最も簡単な方法は、既存のByteBufefrを忘れて新しいものを割り当てることです。公式の文書ではそうは言いませんが、すべての既知の実装は新しいバッファのメモリをゼロにします。詳細は、http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6535542を参照してください。

1

DNAに言及しているように、予め充填されたバッファーを有し、ByteBuffer.put(ByteBuffer)を使用することはおそらく最も速い移植可能な方法です。

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の実装とプラットフォームのいくつかの知識が必要です。それは実用的ではない場合は、適用可能な場合Arrays.fillUnsafe.putLongのいずれかを利用するには、このような何かを行うことができます。ここでは、JACを使用している場合のOracle JREの設定方法について説明します(これは、os.archシステムプロパティにアクセスするための便利で標準的な方法としてPlatform.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"); 
関連する問題