LRU原理と分析
LRUは、最低使用頭文字であること、最も最近のデータを使用LRUキャッシュは、最新のデータが読み与える、削除され、「最低使用」に変換されます。ほとんどの場合、そのLRUキャッシュを使用し、また、最も多くを読んで、読んで、私たちは、システムのパフォーマンスを向上させることができます。
LRUは達成します
1.新しいデータがリンクリストの先頭に挿入されています。
2.たびにキャッシュヒット(すなわち、キャッシュデータをアクセスする)、データがリンクリストの先頭に移動されます。
リストがいっぱいになると3、リンクリストデータの尾は破棄されます。
LRU分析
[ヒット]
ホットデータ、LRUの良い効率が、散発的がある場合は、定期的なバッチ操作は、LRUの急激な減少につながるヒット率、キャッシュ汚染は非常に深刻です。
[複雑]
シンプル。
[費用]
データ・ブロック・インデックス・ヒットを見つけるために、リストを横断に必要なヒットは、その後、頭部にデータを移動する必要があります。
LRUは達成します
ディテール
添加元素时,放到链表头
缓存命中,将元素移动到链表头
缓存满了之后,将链表尾的元素删除
LRUアルゴリズム
- 二重にリンクされたリストには、データを保存するために使用することができます
- 使用ハッシュO(1)アクセスを実現
LRUアルゴリズム(ゴー言語)groupcache
https://github.com/golang/groupcache/blob/master/lru/lru.goを
出典シンプルコメント:
パッケージLRU 輸入「コンテナ/リスト」 //キャッシュの構造、定義されたLRUキャッシュはスレッドセーフではありません タイプのキャッシュ構造体{ //上限数、0は無制限です MaxEntries int型 削除//ときは、オプションのコールバック関数を追加することができます OnEvicted FUNC(キーキー、値インタフェース{}) リンクリストを使用してセーブデータLL * list.List // キャッシュ地図【インターフェース{}] * list.Element //マップ } //キーは、比較される任意の値であるhttp://golang.org/ref/spec#Comparison_operators } {キーインターフェイスを入力 タイプ・エントリ構造体{ キーキー 値インターフェース{} } //新しいキャッシュオブジェクトを作成します。 FUNC新(maxEntries int型)*キャッシュ{ リターン&キャッシュ{ MaxEntries:maxEntries、 LL:list.New()、 キャッシュ:メイク(マップ[インターフェイス{}] * list.Element) } } //キャッシュ内に新しい値を追加 FUNC追加(*キャッシュC)(キーキー、値インタフェース{}){ もしc.cache ==ゼロ{ c.cache =メイク(マップ[インターフェイス{}] * list.Element) c.ll = list.New() } = c.cache [キー];:EE、OKであれば OK { //キャッシュヒットは、リストの先頭に移動します c.ll.MoveToFront(EE) ee.Value。(*エントリー).VALUE =値 リターン } //リストの先頭にデータを追加 ELE:= c.ll.PushFront(&エントリ{キー、値}) c.cache [キー]はそれを= もしc.MaxEntries!= 0 && c.ll.Len()> c.MaxEntries { //要素への最後のフルアクセスを削除します c.RemoveOldest() } } //代わりに、キャッシュから値を取得します。 FUNC(C *キャッシュ)を取得します(キーキー)(値インタフェース{}、[OK]をブール値){ もしc.cache ==ゼロ{ リターン } ELE場合、ヒット:= c.cache [キー]。ヒット{ //キャッシュヒット、ヒットの要素は、リストの先頭に移動します c.ll.MoveToFront(ELE) ele.Valueを返します。(*エントリー).VALUE、真 } リターン } //指定されたキー要素を削除 FUNC(C *キャッシュ)を削除(キーキー){ もしc.cache ==ゼロ{ リターン } ELE場合、ヒット:= c.cache [キー]。ヒット{ c.removeElement(ELE) } } //最後の訪問の要素を削除します FUNC(C *キャッシュ)RemoveOldest(){ もしc.cache ==ゼロ{ リターン } ELE:= c.ll.Back() もしELE!= nilの{ c.removeElement(ELE) } } FUNC(C *キャッシュ)removeElement(E * list.Element){ c.ll.Remove(E) KV:= e.Value(*エントリー)。 削除(c.cache、kv.key) もしc.OnEvicted!= nilの{ c.OnEvicted(kv.key、kv.value) } } //キャッシュバッファ数 FUNCレン(){int型(*キャッシュC) もしc.cache ==ゼロ{ 0を返します } リターンc.ll.Len() }
LRU-K
Kは、最も最近使用されたLRU-Kの数を表し、したがってLRU LRU-1とみなすことができます。LRU-Kの主な目的は、問題「キャッシュ汚染」LRUアルゴリズムを解決することであり、核となるアイデアは、のために「最近使用した1時間」の基準を拡張することで、「最近使用したK回。」
実現
LRUを比較すると、より多くの履歴ビーイングのためのキューを維持するために、LRU-Kの必要性は、すべてのキャッシュされたデータを記録してアクセス。アクセスデータの数は、キャッシュにデータの前にK回に達した場合のみ。データを排除するときに必要な、LRU-Kは、現在の時刻から最大のデータをK番目のアクセス時間を排除するであろう。詳細は、以下を実現します:
1.データは、最初のアクセス履歴リストに追加、アクセスされます。
2.履歴リスト内のデータへのアクセスは、その後除去特定のルール(FIFO、LRU)に従ってK訪問し、達していない場合。
3.データ・アクセス履歴キューへのアクセス回数がK回に達したときに、インデックスデータは、時間によって再注文したキャッシュに履歴キュー、キューデータから削除され、このデータをキャッシュし、キャッシュキューされます。
4.データバッファキューを並べ替え、再度アクセスされた後。
キュー行バッファのデータを排除する5.必要性、すなわち、データの最後に、段階的に廃止:データ消去「今、最も古いから最後から二番目のK訪問を」。
LRU LRU-Kは、LRUの欠点を回避できる一方、LRU-2の実用的なアプリケーションは、様々な要因のために最良の選択である、という利点を有する、LRU-3以上は、K値が高いヒット率が、貧しい適応となり、これは、過去のデータへのアクセス記録へのアクセスの多くはクリアが必要です。
分析
[ヒット]
LRU-Kは、ヒット率がLRUより高いによって引き起こされる「キャッシュ汚染」の問題を低減します。
[複雑]
LRU-K・キューは、優先キュー、アルゴリズムの複雑さとコストが比較的高いです。
[費用]
LRU-Kはまた、それらのオブジェクトを記録する必要があるため、アクセスが、メモリの消費量がよりLRU以上になるよう、キャッシュ内に配置されていない、場合に大量のデータ、メモリ消費量がより印象的であろう。
ソートするのに必要な時間に基づいて、LRU-Kは、(並べ替えたときに段階的に廃止することができ、それが瞬時に並べ替えることができます)、CPUの消費量は、LRUよりも高くなっています。