19

キャッシュされたオブジェクトへの WeakReferences を使用して、メモリ不足の場合にそれらをキャッシュから自動的に削除するキャッシュがあります。私の問題は、キャッシュされたオブジェクトがキャッシュに格納された直後に収集されることです。キャッシュは 64 ビット アプリケーションで実行され、4 ギガを超えるメモリがまだ使用可能な場合でも、キャッシュされたすべてのオブジェクトが収集されます (通常、それらはその時点で G2 ヒープに格納されます)。プロセス エクスプローラーが示すように、手動で誘発されるガベージ コレクションはありません。

オブジェクトの寿命を少し延ばすためにどのような方法を適用できますか?

4

7 に答える 7

17

ジョシュが言ったように、WeakReferenceとGCに対する将来の動作の変更に翻弄されるため、キャッシュされたオブジェクトを参照する主要な手段としてWeakReferencesを使用することは実際には素晴らしいアイデアではありません。

ただし、キャッシュに何らかの復活機能が必要な場合は、パージが保留されているアイテムにWeakReferencesを使用すると便利です。アイテムが排除基準を満たしている場合、アイテムをすぐに排除するのではなく、その参照を弱参照に変更します。GCされる前に何かがそれを要求した場合、その強力な参照を復元すると、オブジェクトは再び生きることができます。これは、有益であるほど頻繁に「復活」するヒット率パターンを予測するのが難しい一部のキャッシュに役立つことがわかりました。

予測可能なヒット率パターンがある場合は、WeakReferenceオプションを使用せず、明示的な削除を実行します。

于 2009-05-30T18:26:14.243 に答える
6

ベースのキャッシュが適している状況が 1 つありWeakReferenceます。それは、クラス内の項目の有用性が、その項目への参照の存在に基づいている場合です。このような状況では、弱いインターニング キャッシュが役立つ場合があります。たとえば、多くの大きな不変オブジェクトをデシリアライズするアプリケーションがある場合、その多くは重複することが予想され、それらの間で多くの比較を実行する必要があります。XYが何らかの不変クラス型への参照である場合、テストX.Equals(Y)両方の変数が同じインスタンスを指している場合は非常に高速ですが、たまたま等しい異なるインスタンスを指している場合は非常に遅くなる可能性があります。逆シリアル化されたオブジェクトがたまたま参照が既に存在する別のオブジェクトと一致する場合、ディクショナリから後者のオブジェクトへの参照を取得すると (1 回の低速な比較が必要)、将来の比較が促進される可能性があります。一方、ディクショナリ内の項目と一致したが、ディクショナリがその項目への唯一の参照である場合、読み込まれたオブジェクトを単に保持する代わりにディクショナリ オブジェクトを使用するメリットはほとんどありません。おそらく、比較のコストを正当化するのに十分な利点ではありません。内部キャッシュの場合、WeakReferencesオブジェクトへの他の参照が存在しなくなったら、できるだけ早く無効化されるのは良いことです。

于 2012-10-30T03:24:00.237 に答える
5

.net では、WeakReference は GC の観点からは参照とはまったく見なされないため、弱参照のみを持つオブジェクトは次の GC 実行で (適切な世代のために) 収集されます。

あなたの経験が示すように、それは弱い参照をキャッシュに完全に不適切にします。

「実際の」キャッシュ コンポーネントが必要です。キャッシングで最も重要なことは、削除ポリシー (つまり、オブジェクトをキャッシュから削除するタイミングに関する規則) がアプリケーションの使用パターンに適切に一致するコンポーネントを取得することです。

于 2009-05-30T19:57:57.133 に答える
3

いいえ、ガベージ コレクターの動作は時間の経過と共に変化する可能性があり、キャッシュが現在の動作に依存するべきではないため、WeakReference は適切ではありません。また、制御できない多くの要因がメモリ不足に影響を与える可能性があります。

.NET のキャッシュには多くの実装があります。CodePlex では、おそらく 10 を超える数を見つけることができます。それに追加する必要があるのは、アプリケーションの現在のワーキング セットを調べて、それをパージのトリガーとして使用するものだと思います。

オブジェクトが頻繁に収集される理由について、もう 1 つ注意してください。GC は、Gen0 オブジェクトのクリーンアップに非常に積極的です。オブジェクトの存続期間が非常に短い場合 (そのオブジェクトへの唯一の参照が弱参照になるまで)、GC はできる限り迅速にクリーンアップすることで、設計どおりの処理を行っています。

于 2009-05-30T17:50:03.723 に答える
0

実際の答えは、構築しようとしているキャッシュの使用特性によって異なります。キャッシュされたオブジェクトが複数の読み取りの短いバーストで使用されることが予想されるプロジェクトの多くで、パ​​フォーマンスを向上させるために WeakReference ベースのキャッシュ戦略をうまく使用しました。他の人が指摘したように、弱い参照は GC の観点からはほとんどガベージであり、次の GC サイクルが実行されるたびに収集されます。メモリ使用率とは関係ありません。

ただし、GC による残忍な行為に耐えられるキャッシュが必要な場合は、System.Runtime.Caching 名前空間によって提供される機能を使用または模倣する必要があります。メモリ使用量がしきい値を超えたときにキャッシュをクリーンアップする追加のスレッドが必要になることに注意してください。

于 2013-05-15T04:14:43.043 に答える