2009-10-29 15 views
5

使用可能なメモリに基づいてサイズを制限するLinkedHashMapを作成したいとします(つまり、freeMemory + (maxMemory - allocatedMemory)が一定のしきい値を下回った場合)。これはキャッシュの形式として使用され、おそらくキャッシング戦略として「最も最近使用された」ものを使用します。LRU使用可能なメモリに基づいてサイズを制限するLinkedHashMap

私は懸念していますが、allocatedMemoryにはガベージコレクションされていないデータも含まれているため、使用されているメモリの量が過大に推定されます。私はこれが持つかもしれない意図しない結果に心配しています。

たとえば、空きメモリが不足していると考えられるため、削除されたアイテムがすぐにガベージコレクションされないため、LinkedHashMapはアイテムの削除を続けることがあります。

誰もこのタイプのことに経験がありますか?私の心配は正当なものですか?もしそうなら、誰かが良いアプローチを提案することができますか?

また、キャッシュを「ロック」することができます。基本的には「ok、今からメモリ使用の問題で何も削除しないでください」と言います。

+0

ここにあなたのアプリケーションはありますか?背景の意図が何であるか分かりませんが、良い答えが出てくるのは難しいです。あなたのHashMapはキャッシュか何ですか? – jprete

+0

jprete、私はこれを明確にしようとしました - あなたは正しいです、そのキャッシュ – sanity

+0

これはGCとJavaメモリ管理が本当に面倒な顔を示す典型的な例です。このようなことをC++で行うのは簡単なことでしょう。 GCを使用すると、deleteやfreeなどのコマンドを実行することはできません。 –

答えて

1

私は偏っていることは知っていますが、実際にはこれをお薦めしますMapMakerキーのGCコレクションであるか、エントリをクリーンアップできるかをより適切に記述する値に応じて、softKeys()またはsoftValues()機能を使用します。

+1

MapMakerを使用したいと思います(私はGoogle Collections私のコードでは)、それは利用可能なメモリに応じてスケールLRUキャッシュのように動作するようにする方法はありますか?また、ガベージコレクションに対応してエントリを削除しないように「ロック」する方法はありますか? – sanity

+1

は "LRUキャッシュのように振る舞います..." - これは、ソフトリファレンスがあなたに与える正確な情報を示しています。 これを「ロック」する - 唯一の賢明な答えは、マップをコピーすることです:Map < Key、Val > strongCache = Maps.newHashMap(cache); –

+0

ごみについてごめんね。<ごみ。プレビューはありませんので、私は脱出する必要があるかどうかを推測しなければなりませんでした。 :( –

0

キャッシュに問題が発生する傾向があります。 IIRCでは、多くの問題を抱えていたSunのJREにSoftCacheがあります。

とにかく、最も簡単なことは、SoftReferenceをマップに使用することです。 SoftReferenceMap.Entryのオーバーヘッドがキャッシュされたデータよりも大幅に低い場合、これは正常に動作します。

WeakHashMapのように、ReferenceQueueを使用してポーリングしたり、スレッドをブロックしたりすることができます(残念なことに、1インスタンスにつき1スレッド)。同期の問題に注意してください。

マップを「ロック」すると、必要に応じて回避することをお勧めします。すべてのデータを強力に参照する必要があります(nullでない場合は削除してください)。それは醜いだろう。

+0

ロックのために、私は単純に全部を通常のHashMapにコピーすることができると思っていた – sanity

+0

まあ、マップの内容をコピーすることができますが、ソフトリファレンスも逆参照する必要があります。ロックの代わりにコピーする方が良い方法です。 –

0

キャッシングシステムを再発明する代わりに、Ehcacheのようなものを使用することを強くお勧めします。それは非常に使いやすく、設定も簡単で、うまく動作します。

0

マットbは言ったように、EhcacheやJbossCacheのようなものは良い最初のステップです。

軽量で処理中のものをお探しの場合は、Googleのコレクションをご覧ください。たとえば、MapMaker(http://google-collections.googlecode.com/svn/trunk/javadoc/index.html?com/google/common/collect/BiMap.html)を使用してSoft/Weakのキーと値を使用してマップを作成すると、余裕のあるアイテムだけがキャッシュされます(LRUを取得しなくても)。

+0

良いリンク:http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/MapMaker.html – nojo

0

私は過去に同じニーズを持っていたし、これは私が私のキャッシュを実装する方法である:

  • 最小と最大のメモリ制限を持っているキャッシュメモリマネージャは、(最大の制限は、それがとにかく重要)があります私はのLinkedHashMapを使用
  • 最大容量(あなたが上限を持っている時間のほとんどは、あなたがX項目以上を保持して行きたくない)&%のメモリ使用量:
  • すべての登録されたキャッシュは、次の(重要な)パラメータがありますキャッシュを保護するReentrantReadWriteLockがあります。
  • すべてのX puts計算されたメモリリミット>許容メモリリミットの場合、エントリごとの平均メモリ消費量とトリガ追い出し(async)を計算します。
  • もちろん、実際のメモリ消費量は実際には計算されませんが、計算されたメモリと実際の値(プロファイラを使用)とを比較すると、十分に近いことがわかります。

私はキャッシュに追加のガードを入れて、メモリベースのエビクションよりも高速になっている場合には退去させようとしていましたが、これまで必要なことは見つけられませんでした。

関連する問題