文字通り、キーの追加および削除時にガベージをまったく生成しない Map または Set の既存の実装を認識していません。
実際、技術的に可能である唯一の方法 (Java では、定義されているMap
およびSet
API を使用) は、エントリ数に厳密な上限を設定することです。実用的な Map および Set の実装には、保持する要素の数に比例する追加の状態が必要です。この状態はどこかに保存する必要があり、現在の割り当てを超えた場合は、そのストレージを拡張する必要があります。Java では、新しいノードを割り当てる必要があることを意味します。
(わかりました、古い役に立たないノードを永久に保持するデータ構造クラスを設計したため、収集可能なガベージは生成されませんでしたが、それでもガベージが生成されています。)
では、実際にこれについて何ができるでしょうか...生成されるゴミの量を減らすために。HashMap
例として見てみましょう:
エントリを削除すると、ガベージが作成されます。ハッシュ チェーンを、チェーン エントリを表すノードを解放しない実装に置き換えない限り、これは避けられません。(そして、それは悪い考えです...空きノードプールのサイズが常に小さいことを保証できない限り。それが悪い考えである理由については、以下を参照してください。)
メインのハッシュ配列のサイズが変更されると、ガベージが作成されます。これは、いくつかの方法で回避できます。
HashMap コンストラクターで 'capacity' 引数を指定して、最初のハッシュ配列のサイズを、サイズを変更する必要がない十分な大きさに設定できます。(しかし、それはスペースを無駄にする可能性があります...特に、 がどれだけ大きくなるかを正確に予測できない場合HashMap
)。
「負荷係数」引数にばかげた値を指定して、HashMap のサイズが決して変更されないようにすることができます。(しかし、その結果、ハッシュチェーンが制限されていない HashMap になり、O(N)
ルックアップ、挿入、削除などの動作になります。
実際、ガベージを作成することは必ずしもパフォーマンスに悪いわけではありません。実際、ガベージ コレクターがノードを収集しないようにノードにハングアップすると、実際にはパフォーマンスが低下する可能性があります。
GC 実行のコスト (最新のコピー コレクターを想定) は、主に次の 3 つの領域にあります。
- ガベージではないノードを見つける。
- それらの非ガベージ ノードを「to-space」にコピーします。
- 「to-space」内のオブジェクトを指すように、他の非ガベージ ノード内の参照を更新します。
(一時停止の少ないコレクターを使用している場合は、他のコストもかかります...一般に、ガベージ以外の量に比例します。)
ガベージの量に実際に依存する GC の作業の唯一の部分は、ガベージ オブジェクトがかつて占有していたメモリをゼロにして再利用できるようにすることです。そして、これは「from-space」全体に対する単一の呼び出しで実行できますbzero
...または仮想メモリのトリックを使用します。
ガベージの作成を避けるために、アプリケーション/データ構造がノードにハングアップするとします。ここで、GC が実行されると、これらの余分なノードをすべてトラバースし、それらに有用な情報が含まれていなくても、それらを「to-space」にコピーするために余分な作業を行う必要があります。さらに、これらのノードはメモリを使用しています。つまり、アプリケーションの残りの部分がガベージを生成すると、ガベージを保持するスペースが少なくなり、GC をより頻繁に実行する必要があります。
また、弱/ソフト参照を使用して GC がデータ構造からノードを取り戻せるようにしている場合、それは GC にとってさらに多くの作業になります...そしてそれらの参照を表すスペース。
注: オブジェクト プーリングが常にパフォーマンスを低下させると主張しているわけではありません。特にプールが予想外に大きくなった場合は、パフォーマンスが低下することがよくあります。
そしてもちろん、それが HashMap や同様の汎用データ構造クラスがオブジェクト プーリングを行わない理由です。もしそうなら、プログラマーが予期していない状況でパフォーマンスが大幅に低下します...そして、本当に壊れてしまうでしょう、IMO.
最後に、HashMap を調整して、同じキーを追加した直後に削除してもガベージが生成されないようにする簡単な方法があります (保証されます)。「追加」された最後のエントリをキャッシュし、次のエントリが追加されたときにのみput
実際に実行する Map クラスにラップします。HashMap
もちろん、これは汎用ソリューションではありませんが、以前の質問のユースケースに対応しています。