2011-12-08 3 views
3

私のアプリケーションで生成されたデータをメモリにキャッシュしたいが、メモリが不足する場合は、データをディスクにスワップしたい。空きメモリが少ない場合にのみデータをディスクにスワップする書き込みキャッシュを実装する方法

理想的には、VMがメモリを必要とし、データをディスクに書き込み、メモリを解放することが理想です。しかし私はの前にOutOfMemoryErrorがどこかで(ほとんどの場合、どのような方法でもキャッシュに関係しないコードで)発生することを通知する方法で自分自身をVMにフックする方法はありません。

java.lang.refの参照クラスは、この場合には使用されていないようですが、その参照メカニズム(ReferenceQueue)は、GCによって参照がすでに再要求された後にのみトリガーされます。それでは、データをディスクに保存するのは遅すぎるでしょう。

ヒープメモリを効率的に管理するための代替手段はありますか? (絶対に避けられないまで、ディスクにスワップしていない)


EDIT1:コメントへの応答では、「OSが既にあなたのためのことを行います」 - メモリOSの量 - これが唯一の問題の一部を覆います割り当てることができるは、限定リソースですです。ここで考慮される必要があるOSが使用できるメモリの量以外の制限もあります

  • VMのアーキテクチャによる制限(32-Bit VM
  • に割り当てることのできるメモリの上限VMのプロセスは、(32-Bit OS
  • 制限は、おそらく場合でも、メモリ不足からそれを防ぐことはできませんだけで無制限のヒープサイズでVMを実行している-Xmxオプション

を使用してVMに課さOS依然として十分な利用可能性がありますが、これは上記の理由でVMに利用できない可能性があります。

+2

ほとんどのオペレーティングシステムがこれを処理します。なぜそれを再実装したいのですか? –

+0

そして、上記のコメントを強化する:http://en.wikipedia.org/wiki/Paging – jweyrich

+0

@George通常、ディスクに何が入っているのか、そうでないのかを選ぶことはできません。非常に頻繁にアクセスしない仮想メモリからロードしたくないミッションクリティカルなデータがあるかもしれませんが、OSはそこに置くことに決めました。 – corsiKa

答えて

0

空きメモリーを繰り返し確認するスレッドを作成して、制限を超えた場合に動作します。

1

利用可能な空きメモリを監視し、それに応じて動作するAPI呼び出しを使用することをお勧めします。

this questionを参照して、JVMで使用可能な空きメモリの量を監視する方法を参照してください。

+0

私はもっと良い方法を望んでいます。空きメモリを監視することは、チェックの間に最悪の場合にアプリケーションが割り当てることができるように、キャッシュが常にメモリを自由に使用する必要があることを意味します。 – Durandal

0

私は内部データベースを使用します(開発のために、Derbyは選択した味に置き換えることを心に留めています)。通常、これらの機能はすでに組み込まれており、キャッシュに保持するデータベースの量を設定できます。

+0

私の知る限りでは、データベース(およびDerby shoulも例外ではありません)は、トランザクションが成功する前に常にすべてをディスクにコミットします。つまり、ディスク上のデータが存在し、その一部がメモリにキャッシュされます。それは微妙ですが、私の場合は決定的な違いです。メモリがあれば、データをディスクに書きたくないのです。 – Durandal

0

純粋なJavaでこれを行うのは非常に難しいことです。これは、あなたがすでにヒントしている理由によるものです。

  • GCがでキックする前に、ヒープがほぼ満杯になるのをあなたは空きメモリが利用可能本当にどのくらいかを決定することができます唯一の方法は、GCを行うことです(とそうでないので、それは、非常に正常ですあまりにも頻繁にそれをしたい)。あなたは、Permanentが80%いっぱいになったときにGCが起きるようにCMSInitiatingOccupancyFractionオプションを使うことができます。管理APIから返された "空きメモリ"の値がおそらくほぼ正しいでしょう(値> 80%の場合) 。もちろん保証はありません。

  • 前述のとおり、ソフトリファレンスはコレクタによって自動的にクリアされてから登録されたキューに追加されるため、ここでは特に役に立ちません。 ダミーのSoftReferenceを作成し、そのエンキューをメモリ不足の兆候として使用します。しかし、タイミングについてはわかりません.JVMのメモリが足りなくなる前にすべてのデータをディスクにダンプすることは保証できますか?おそらくそうではありません。

それは特定のサイズ、例えばに達したときに、あなたが代わりにディスクにキャッシュをフラッシュでしたそれが500MBを超えたら、それをフラッシュしてください?

プライベートマッピングを持つMappedByteBufferを使用できますか?データはディスクにフラッシュされません。私が正しく覚えていれば、あなたが書いたデータは、少なくともヒープの "直接"メモリ(少なくともLinuxでは)に格納されているので、ヒープを消費することはありませんが、それを確認してください。 RAMが使い尽くされたら、もちろんスワップを使い始めるでしょう。

+0

設定されたメモリ使用量でディスクにフラッシュしても問題は発生しません。それ以上のオプションがない場合はフォールバックプランになります(最大メモリのパーセンテージまたは設定された制限値の1 MB)。あなたはMappedByteBuffersの提案は有望に見える、あまりにも悪いJREのソースはあまり有用ではない、それは多くの肉を表示せずにネイティブになります。私は間違いなくそれらをチェックアウトします。 – Durandal

0

メモリマップファイルの使用を検討しましたか? http://en.wikipedia.org/wiki/Memory-mapped_file

これは、VMに割り当てられたメモリよりも大きなメモリにアクセスできないという問題を解決します。

関連する問題