1

現在、大量のテキスト (数百 MB から数 GB のテキスト - DBpedia データセット) を使用するプロジェクトに取り組んでいます。スペースを節約するために、文字列を数値にマップし、印刷する必要がある場合にのみ文字列を操作します。データを処理するアルゴリズムを高速化するためにCache、キーと値のキャッシュとして機能するクラスを設計しました。もちろん問題は、プログラムが長時間実行されると、キャッシュが非常に大きくなることです。

現時点で私が管理している方法は、キャッシュを特定のエントリ数に制限することです。このソリューションは機能していますが、それほど優れていません。より柔軟なアプローチは、すべてのキャッシュにある程度のメモリ制限を設け、制限に達したときにキャッシュを無効にするか、キャッシュの重要性とサイズに応じて一部のキャッシュを空にすることです。

各インスタンスが使用しているメモリ量を報告できるように、キャッシュのサイズをバイト単位で返す sizeB() メソッドを実装することを検討しています。しかし、もちろん、これはキャッシュをいつ停止するかという問題を解決しません...おそらく、すべてのメモリ使用量を手動で追跡する必要があります。おそらくCacheFactory、すべてのキャッシュが登録され、制限に達すると空になるシングルトンもありますか?

そのようなことを行うための「標準的な」テクニックがあるかどうか疑問に思っていました。検索すべきイディオム/パターンはありますか?

また、自分でメモリ使用量を追跡する方がよいでしょうか (移植性は高くなりますが、より手間がかかるようです)、Linux で /prco/pid を読み取るなどの手法を使用することもできます。

4

1 に答える 1

1

はい、キャッシュとメモリのリバランスには標準的な手法があります。最も単純なアプローチは、あなたが考えていることに従うでしょう-キャッシュ「ファクトリ」または「マネージャ」を作成します。キャッシュオブジェクトをオンデマンドで割り当て、各オブジェクトにはサイズ制限があります(64バイトのプリセットサイズを持つCPUキャッシュラインと考えてください)。マネージャーに割り当てられたキャッシュオブジェクトの数だけを知っていると、使用されているメモリの量を概算し、それを実行しているマシンやOSのタイプなどに基づいて知っているtotal_max_limitと比較できます。したがって、total_max_limitに達して一部のキャッシュオブジェクトを解放する必要がある場合、最も一般的に使用されるアプローチはLRU(破棄するために最も最近使用されていないキャッシュオブジェクトを選択する)です。これを実装するには、マネージャー内のキャッシュオブジェクトへのポインターを両端キューに格納し、キャッシュオブジェクトにアクセスすると、マネージャーに(キャッシュオブジェクト構造のポインターを介して)「アクセス済みとしてマーク」という意味でポインターを移動するように指示します。 dequeの前にあるこのキャッシュオブジェクトに。これは、両端キューの最後のポインター(* tail)が、最も最近使用されていないキャッシュオブジェクトを参照していることを意味します。そしてfactory.rebalance()は単にpop_backし、返されたオブジェクトを解放します。

他のアルゴリズムもありますが、LRUが最も一般的に使用されるアルゴリズムです。優先キャッシュは、それを使用して実装することもできます。必要なのは、いくつかの「キャッシュマネージャー」を作成し、それらのtotal_max_limitsを分散して、優先度の高いものがより多くのメモリを取得し、優先度の低いものがますます少なくなるようにすることです。その結果、優先度の低いものが得られます。より速く追い出され、より優先度の高いものがメモリ/キャッシュに常駐します。このアプローチは、各キャッシュに対して毎回重みベースの式を計算して、この特定のキャッシュオブジェクトを両端キューの先頭からどれだけ移動するかを選択するよりも優れたパフォーマンスを発揮する可能性があります。

于 2012-05-05T09:27:35.630 に答える