局所性がパフォーマンスにまったく役立つとは思えません-確かに、小さなオブジェクトはヒープの同じ領域に同時に作成される傾向があります(ただし、これはCにも当てはまります)。時間の経過とともに、残っているこれらの小さなオブジェクトは緊密に圧縮されます。ヒープの関連領域であり、Cスタイルの割り当てよりも有利なのはおそらくこれです。ただし、これらの小さなオブジェクトだけを使用するプログラムを見せてください。すべてを実行するプログラムを紹介します。スタックで使用されるすべてのオブジェクトを渡すプログラムを見せてください。スピードで叫ぶものを紹介します。
メモリの割り当て解除は、割り当てを解除する必要がないため、短期的にはパフォーマンス上の利点になります。ただし、ガベージコレクターが起動すると、この利点はなくなります。ただし、通常、収集はシステムで(理論的には)他に何も起きていないときに行われるため、コストは事実上無効になります。
ヒープの圧縮も割り当てに役立ちます。すべての割り当てはヒープの最初から行うことができ、メモリマネージャは、適切なサイズの次の空き領域ブロックを探すためにヒープを歩く必要はありません。ただし、従来のシステムでは、複数の固定ブロックヒープを使用することで同じ速度を得ることができます(つまり、常に必要なブロックのサイズにヒープから割り当て、常に固定ブロックを割り当てるため、ヒープをウォークするだけで最初の空きブロックを見つけます。これはビットマップを使用して削除できます)
したがって、全体として、もちろんベンチマークを除いて、ほとんどメリットはありません。私の経験では、GCは、ユーザーが大量のメモリ割り当てを必要とする新しいページをロードするなどの操作を行ったために、通常はシステムメモリがいっぱいになったときに、ジャンプして劇的に遅くなる可能性があります。 。これにはコレクションが必要でした。
また、大量のメモリを使用する傾向があります。「メモリは安い」がGC言語の信条であるため、プログラムはこれを念頭に置いて作成されます。つまり、メモリの割り当ては、特に一時オブジェクトや中間オブジェクトではるかに一般的です。これがよく知られている証拠については、StringBuilderクラスを参照してください。文字列はこれを使用して「解決」できますが、他の多くのオブジェクトは依然としてワイルド放棄で割り当てられます。大量のメモリを使用するプログラムは、RAM IOに苦労します。使用するメモリはすべてCPUキャッシュに取り込む必要があり、使用するメモリが多いほど、CPUMMが実行する必要のあるIOも多くなります。間違った状況でパフォーマンスを殺します。
さらに、GCが発生した場合は、ファイナライズされたオブジェクトも処理する必要があります。これは以前ほど悪くはありませんが、ファイナライザーの実行中にプログラムを停止する可能性があります。
古いJavaGCはパフォーマンスにとって恐ろしいものでしたが、多くの研究によって大幅に改善されましたが、それでも完全ではありません。
編集:ローカリゼーションについてもう1つ、配列を作成していくつかのアイテムを追加し、次に割り当てのロードを実行してから、別のアイテムを配列に追加することを想像してください-GCシステムでは、追加された配列要素はローカライズされません圧縮後、配列内の各オブジェクトは個別のアイテムとしてヒープに格納されます。これが、ローカリゼーションの問題が、実際に考えられているほど大きな問題ではないと思う理由です。ここで、それをバッファーが割り当てられ、オブジェクトがバッファー・スペース内に割り当てられている配列と比較します。新しいアイテムを追加するには、再割り当てとコピーが必要になる場合がありますが、読み取りと変更は非常に高速です。