この記事に記載されている2つのキャッシュモデルは、メモリ内のデータのキャッシュモデルを指します。
どんな言語に関係なく、繰り返しの操作や読み取りを避けるために、いくつかのデータをメモリに配置する必要があるかもしれません。最も一般的なシナリオはjQueryセレクターです。いくつかのDOM要素の選択は非常に時間がかかります。私たちは、私たちが電話するたびにDOMツリーを反転させることなく、これらのデータをキャッシュすることを望んでいます。
それを保存しますが、量がなければなりません!すべての履歴データをメモリに入れることはできません。結局のところ、現在のメモリ容量は依然として非常に哀れです。メモリが十分に大きい場合でも、理論の各スレッドによって割り当てられたメモリはまだ限られています。
問題は、どうすれば本当に有用なデータを効率的にキャッシュできるのでしょうか?これには、排除アルゴリズムが含まれ、有用なデータを保存するためにジャンクデータを排除する必要があります。
いくつかの一般的なアイデアがあります:
FIFO:これは、最初の最初のキューである最初のキャッシュデータであり、最初に排除されました。このモデルは、有名なjQueryフレームワーク内で使用されます。
LRU:ダブルリンクリスト構造は、新しいデータが保存されるたびに、リンクリストのヘッダーに直接配置されます。毎回アクセスされるデータは、リンクリストのヘッダーにも転送されます。このように、リンクリストの最後にあるデータは、最近使用されておらず、排除されるものです。
2つの人:FIFO+ LRU。 FIFOは主に初めて保存されたデータを保存し、LRUは少なくとも2回使用されているホットスポットデータを保存します。このアルゴリズムは、ヒット率が高く、順応性が強く、複雑さが低くなっています。
他にも多くの除去アルゴリズムがありますが、実際に使用される2種類の種類しかありません。それらのアルゴリズムは複雑ではなく、実装が容易であり、実行効率が高く、キャッシュヒット率はほとんどの場合に受け入れられます。結局のところ、キャッシュアルゴリズムにはCPU消費も必要です。それが複雑すぎる場合、ヒット率は改善されていますが、損失の価値はありません。キャッシュからデータを取得すると、元の場所からフェッチするよりも時間がかかると想像してください。キャッシュの使用は何ですか?
特定の理論については話しません。オンラインでいくつかありますが、私はそれらをあまり理解していません。今日は、2つの2つのキャッシュモデルのJavaScriptバージョンを共有します。
最初にそれを使用する方法について話しましょう、それは非常に簡単です。
基本的な使用方法は次のとおりです。
[/コード]
var tq = inittwoqueues(10);
tq.set( "key"、 "value");
tq.get( "key");
[/コード]
初期化するときは、キャッシュ容量を指定するだけです。 FIFO+LRUは内部的に実装されているため、実際の容量は指定された容量の2倍であることに注意してください。上記の例は、実際に20を保存できる10(キー価値ペア)を指定します。
容量のサイズは、実際のアプリケーションシナリオに従って決定する必要があります。小さすぎる場合、ヒット率が低く、効率が低く、極端が反対であり、自分で測定する必要があります。
開発プロセス中、キャッシュ効果を確認するために、キャッシュプールを開発バージョンに初期化できます。
コードコピーは次のとおりです。
var tq = inittwoqueues(10、true);
tq.hitratio();
最後にパラメーターを追加するだけで、真実です。この方法で初期化されたキャッシュプールは、ヒット率を自動的にカウントし、ヒット率はHitratioメソッドを介して取得できます。このパラメーターが追加されていない場合、Hitratioメソッドによって取得されたヒット率は常に0です。
統計的ヒット率は間違いなくリソースを消費するため、生産環境でオンにすることはお勧めしません。
コードを共有する時が来ました:
コードコピーは次のとおりです。
(function(exports){
/**
*継承のための純粋なクラス
* @constructor
*/
関数fn(){}
fn.prototype = elimination.prototype;
/**
*リンクされたリストに基づくキャッシュ排除アルゴリズムの親クラス
* @param maxlengthキャッシュ容量
* @constructor
*/
関数除去(maxlength){
this.container = {};
this.length = 0;
this.maxlength = maxlength || 30;
this.linkhead = this.buildnode( "" "、" ");
this.linkhead.head = true;
this.linktail = this.buildnode( "" "、" ");
this.linktail.tail = true;
this.linkhead.next = this.linktail;
this.linktail.prev = this.linkhead;
}
elimination.prototype.get = function(key){
新しいエラーをスローします(「この方法はオーバーライドする必要があります!」);
};
elimination.prototype.set = function(key、value){
新しいエラーをスローします(「この方法はオーバーライドする必要があります!」);
};
/**
*リンクリストにノードを作成します
* @paramデータノードに含まれるデータ、つまりキャッシュされたデータ値
* @paramキーノードの一意の識別子、つまりキャッシュキー
* @returns {{}}
*/
elimination.prototype.buildnode = function(data、key){
var node = {};
node.data = data;
node.key = key;
node.use = 0;
ノードを返す;
};
/**
*リンクリストのヘッダーからノードがポップアップします
* @returns {*}
*/
elimination.prototype.shift = function(){
var node = null;
if(!this.linkhead.next.tail){
node = this.linkhead.next;
this.linkhead.next = node.next;
node.next.prev = this.linkhead;
this.container [node.key];
this.length--;
}
ノードを返す;
};
/**
*リンクリストのヘッダーからノードを挿入します
* @paramノードノードオブジェクト
* @returns {*}
*/
elimination.prototype.unshift = function(node){
node.next = this.linkhead.next;
this.linkhead.next.prev = node;
this.linkhead.next = node;
node.prev = this.linkhead;
this.container [node.key] = node;
this.length ++;
ノードを返す;
};
/**
*リンクリストの端からノードを挿入します
* @paramノードノードオブジェクト
* @returns {*}
*/
elimination.prototype.append = function(node){
this.linktail.prev.next = node;
node.prev = this.linktail.prev;
node.next = this.linktail;
this.linktail.prev = node;
this.container [node.key] = node;
this.length ++;
ノードを返す;
};
/**
*リンクリストの端からノードがポップアップします
* @returns {*}
*/
elimination.prototype.pop = function(){
var node = null;
if(!this.linktail.prev.head){
node = this.linktail.prev;
node.prev.next = this.linktail;
this.linktail.prev = node.prev;
this.container [node.key];
this.length--;
}
ノードを返す;
};
/**
*リンクされたリストから指定されたノードを削除します
* @paramノードノードオブジェクト
* @returns {*}
*/
elimination.prototype.remove = function(node){
node.prev.next = node.next;
node.next.prev = node.prev;
this.container [node.key];
this.length--;
ノードを返す;
};
/**
*ノードにアクセスするときに実行する必要がある処理は、ノードをリンクリストのヘッダーに移動することです
* @paramノード
*/
elimination.prototype.use = function(node){
this.remove(node);
this.unshift(node);
};
/**
* LRUキャッシュ除去アルゴリズムの実装
* @constructor
*/
関数lru(){
Elimination.Apply(これ、引数);
}
lru.prototype = new fn();
lru.prototype.get = function(key){
var node = undefined;
node = this.container [key];
if(node){
this.use(node);
}
ノードを返す;
};
lru.prototype.set = function(key、value){
var node = this.buildnode(value、key);
if(this.length === this.maxlength){
this.pop();
}
this.unshift(node);
};
/**
* FIFOキャッシュエリミネーションアルゴリズムの実装
* @constructor
*/
function fifo(){
Elimination.Apply(これ、引数);
}
fifo.prototype = new fn();
fifo.prototype.get = function(key){
var node = undefined;
node = this.container [key];
ノードを返す;
};
fifo.prototype.set = function(key、value){
var node = this.buildnode(value、key);
if(this.length === this.maxlength){
this.shift();
}
this.append(node);
};
/**
* LRUおよびFIFOアルゴリズムのカプセル化は、新しいTwoqueues Cache Elimination Algorithmになりました
* @param maxlength
* @constructor
*/
関数エージェント(maxlength){
this.getCount = 0;
this.hitcount = 0;
this.lir = new fifo(maxlength);
this.hir = new lru(maxlength);
}
agent.prototype.get = function(key){
var node = undefined;
node = this.lir.get(key);
if(node){
node.use ++;
if(node.use> = 2){
this.lir.remove(node);
this.hir.set(node.key、node.data);
}
}それ以外{
node = this.hir.get(key);
}
ノードを返す;
};
agent.prototype.getx = function(key){
var node = undefined;
this.getCount ++;
node = this.get(key);
if(node){
this.hitcount ++;
}
ノードを返す;
};
agent.prototype.set = function(key、value){
var node = null;
node = this.lir.container [key] || this.hir.container [key];
if(node){
node.data = value;
}それ以外{
this.lir.set(key、value);
}
};
/**
*ヒット率を取得します
* @returns {*}
*/
agent.prototype.hitratio = function(){
var ret = this.getCount;
if(ret){
ret = this.hitcount / this.getCount;
}
返品;
};
/**
*外部インターフェイス
* @param maxlengthキャッシュ容量
* @param devこれが開発環境であるかどうかにかかわらず、開発環境はヒット率をカウントします。
* @returns {{get、set:function、hitratio:function}}}
*/
exports.inittwoqueues = function(maxlength、dev){
var api = new Agent(maxlength);
戻る {
get :( function(){
if(dev){
return function(key){
var ret = api.getx(key);
Ret && ret.data;
};
}それ以外{
return function(key){
var ret = api.get(key);
Ret && ret.data;
};
}
}())、
set:function(){
api.set.apply(api、arguments);
}、
hitratio:function(){
api.hitratio.apply(api、arguments)を返します。
}
};
};
}(これ));
最後に、キャッシュアルゴリズムを実際のアプリケーションシナリオと組み合わせる必要があることをもう一度思い出させたいと思います。ユニバーサルアルゴリズムがなければ、最高のアルゴリズムは最高です!