1. ホーム
  2. java

[解決済み] ByteBuffer.allocate() vs. ByteBuffer.allocateDirect()

2022-04-28 04:50:50

質問

宛先 allocate() または allocateDirect() それが問題なのです。

この数年、私はただ、「この先、どうなるんだろう」と考えていました。 DirectByteBuffer はOSレベルで直接メモリマッピングされるため、get/putの呼び出しでは HeapByteBuffer s. 私は今まで、この状況に関して正確な詳細を知ることにあまり興味がありませんでした。私は、2つのタイプのうち、どちらの ByteBuffer の方が速いのか、どのような条件下で速いのか。

解決方法は?

Ron Hitchesの素晴らしい著書 Java NIO は、あなたの質問に対する良い答えになると思われるものを提供しているようです。

<ブロッククオート

オペレーティングシステムは、I/O の操作をメモリ領域に対して行います。これらの メモリ領域は、オペレーティングシステムから見て システムは、連続した バイトの列です。当然といえば当然ですが バイトバッファだけが に参加することができます。 の操作を行うことができます。また、次のことを思い出してください。 オペレーティングシステムが直接アクセスする プロセスのアドレス空間、この場合は この場合、JVMプロセスは、転送するために データです。つまり、メモリ領域 I/O操作のターゲットとなるのは は連続したバイト列である。このため JVMでは、バイトの配列は、そのような配列にならないことがあります。 メモリに連続的に格納されているか、または ガベージコレクタは、いつでも移動させることができます。 となります。配列はJavaではオブジェクトであり その中のデータの格納方法 オブジェクトはJVMによって異なる可能性があります。 を実装しています。

このため ダイレクトバッファが導入されました。ダイレクト バッファは相互作用のために設計されています。 チャネルやネイティブI/Oルーチンと を格納するために最善の努力をします。 バイトの要素をメモリ領域で チャネルが直接、または生で使用することができます。 ネイティブコードで オペレーティング・システムから排出または充填する メモリ領域を直接使用します。

ダイレクトバイトバッファは、通常 I/O操作のための最良の選択です。そのため をサポートするように設計されています。 が利用できる効率的なI/Oメカニズム JVM 非直接バイト・バッファを使用することができます。 チャネルに渡すことができますが、チャネルに渡すと が発生し、パフォーマンスが低下します。それは 通常、非直接的な バッファをネイティブのターゲットにすることは I/O操作。もし、非直接的な ByteBufferオブジェクトをチャネルに渡して 書き込みを行う場合、チャネルは暗黙のうちに は、呼び出しのたびに次のようになります。

  1. 一時的に直接ByteBufferを作成する オブジェクトを作成します。
  2. 非直結の内容をコピーする バッファを一時的なバッファに変更します。
  3. 低レベルI/O操作の実行 一時バッファを使用する。
  4. テンポラリ・バッファ・オブジェクトは のスコープから外れ、最終的にはガベージ が収集されます。

このため、潜在的にバッファ をコピーし、I/Oのたびにオブジェクトが乱れる。 というのは、まさに は避けたいところです。しかし 実装によっては、そうでない場合もあります。 ということです。ランタイムはおそらく ダイレクトバッファをキャッシュして再利用するか を向上させるために、他の巧妙なトリックを実行します。 スループットが向上します。もし、単に バッファは一度だけ使用するものです。 その差は大きくありません。一方 一方 バッファは ハイパフォーマンスシナリオでは ダイレクトバッファーの割り当ての方が良い を作成し、それを再利用する。

ダイレクトバッファはI/Oに最適です。 が、より高価になる可能性があります。 は、非ダイレクトバイトバッファよりも作成されます。 ダイレクトバッファが使用するメモリは へのコールスルーで確保されます。 ネイティブ、オペレーティングシステム固有の コードで、標準のJVMヒープを迂回します。 ダイレクト・コードのセットアップと削除 バッファは ヒープ常駐型バッファよりコストがかかる。 ホストオペレーティングシステムに依存 とJVMの実装があります。そのため ダイレクトバッファのメモリ格納領域 はガベージコレクションの対象外です。 というのも、これらは標準的な JVMヒープ

を使用した場合のパフォーマンスのトレードオフは ダイレクトバッファと非ダイレクトバッファは は、JVM、オペレーティング・システムによって大きく異なります。 とコード設計を行います。メモリを確保することで ヒープ外の環境では アプリケーションに新たな が、JVMが知らないうちに このような場合 を追加することができます。 を実現できているかを確認してください。 ということです。私がお勧めするのは 古いソフトウェアの格言: まずそれを作る そして、速くする。心配することはありません。 最適化を前面に押し出し過ぎない。 正しさに集中することです。その JVMの実装は バッファーキャッシングなどの 最適化することで 必要なパフォーマンスを得ることができます。 あなたの側で不必要な努力をする必要はありません。