putX() 呼び出しが容量をオーバーランした場合に動的に拡張される java.nio.ByteBuffer の実装を見たことがありますか?
このようにしたい理由は 2 つあります。
- 事前にどのくらいのスペースが必要かわかりません。
- スペースがなくなるたびに new ByteBuffer.allocate() を実行してから一括 put() を実行したくありません。
putX() 呼び出しが容量をオーバーランした場合に動的に拡張される java.nio.ByteBuffer の実装を見たことがありますか?
このようにしたい理由は 2 つあります。
非同期 I/O が機能するには、連続メモリが必要です。C では配列の再割り当てを試みることができますが、Java では新しいメモリを割り当てる必要があります。に書き込み、送信する準備が整った時点で にByteArrayOutputStream
変換できます。ByteBuffer
欠点は、メモリをコピーしていることです。効率的な IO の鍵の 1 つは、メモリがコピーされる回数を減らすことです。
ByteBufferは、その設計概念が特定の配列の単なるビューであり、直接参照することもできるため、実際にはこのように機能することはできません。奇妙なことが起こらずに、そのアレイをより大きなアレイに交換することはできませんでした。
使用したいのはですDataOutput
。最も便利な方法は、(プレリリースの)Guavaライブラリを使用することです。
ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.write(someBytes);
out.writeInt(someInt);
// ...
return out.toByteArray();
ただし、ByteArrayOutputStreamからDataOutputStreamを手動で作成し、それらをAssertionErrorsにチェーンすることで偽のIOExceptionを処理することもできます。
Mina IOBuffer https://mina.apache.org/mina-project/userguide/ch8-iobuffer/ch8-iobuffer.htmlをご覧ください。これは、置き換えのドロップです(ByteBufferをラップします)
ただし、必要以上に割り当てて、あまり気にしないことをお勧めします。バッファ(特に直接バッファ)を割り当てると、OSは仮想メモリを提供しますが、実際に使用された場合にのみ物理メモリを使用します。仮想メモリは非常に安価である必要があります。
もう 1 つのオプションは、大きなバッファーを持つダイレクト メモリを使用することです。これは仮想メモリを消費しますが、使用するだけの物理メモリしか使用しません (通常は 4K のページごと)。
したがって、1 MB のバッファーを割り当てると、1 MB の仮想メモリが消費されますが、実際に使用するアプリケーションに物理ページを提供する OS だけです。
その結果、アプリケーションが大量の仮想メモリを使用しているのに、比較的少量の常駐メモリが使用されていることがわかります。
Netty のDynamicChannelBufferも見てみる価値があるかもしれません。私が便利だと思うものは次のとおりです。
slice(int index, int length)
ベクトルは継続的な成長を可能にします
Vector<Byte> bFOO = new Vector<Byte>();
bFOO.add((バイト) 0x00);`
何かをシリアル化するには、エントリにオブジェクトが必要です。あなたができることは、オブジェクトをオブジェクトのコレクションに入れ、その後ループを作成してイテレータを取得し、それらをバイト配列に入れることです。次に、 を呼び出しますByteBuffer.allocate(byte[].length)
。それが私がしたことであり、それは私のために働きました。