首頁  >  文章  >  web前端  >  詳解Nodejs基於LRU演算法實作的快取處理操作方法

詳解Nodejs基於LRU演算法實作的快取處理操作方法

高洛峰
高洛峰原創
2017-03-19 09:45:421449瀏覽

這篇文章主要介紹了Nodejs基於LRU演算法實現的快取處理操作,結合具體實例形式分析了LRU演算法的原理、功能以及nodejs使用LRU演算法實現快取處理操作的相關實作技巧,需要的朋友可以參考下

本文實例講述了Nodejs基於LRU演算法實現的快取處理操作。分享給大家供大家參考,具體如下:

LRU是Least Recently Used的縮寫,即最近最少使用頁面置換演算法,是為虛擬頁式存儲管理服務的,是根據頁面調入內存後的使用情況進行決策了。由於無法預測各頁面將來的使用情況,只能利用「最近的過去」作為「最近的將來」的近似,因此,LRU演算法就是將最近最久未使用的頁面予以淘汰。

可以用一個特殊的堆疊來保存目前正在使用的各個頁面的頁面號碼。當一個新的程序存取某頁時,便將該頁號壓入棧頂,其他的頁號往棧底移,如果記憶體不夠,則將棧底的頁號移除。這樣,棧頂總是最新被造訪的頁面的編號,而棧底則是最近最久未造訪的頁面的頁號。

如輸入下列序列時:4,7,0,7,1,0,1,2,1,2,6

結果為:

4
4        7
4        7        0
#4          7        1
4        7        1       
4        7        0        1         0        2        1
4        7        0           1        2     為一般緩存。



function CacheLRU(capacity) {
/* 利用Buffer写的一个LRU缓存,capacity为缓存容量,为0时不限容量。
myCache = new CacheLRU(capacity); //构造缓存
myCache.get(key); //读取名为key的缓存值
myCache.put(key, value); //写入名为key的缓存值
myCache.remove(key); //删除名为key的缓存值
myCache.removeAll(); //清空缓存
myCache.info(); //返回myCache缓存信息
LRU原理:对所有缓存数据的key构建hash链表,当对某一数据进行get或put操作时,将其key提到链表前端(最新)。当进行put数据超出容量时,删除链表尾端(最旧)的缓存数据。
hash链表操作可直接定位key,无需历遍整个hash对象,故读写极快。缓存容量不再影响读写速度。
*/
  this.capacity = capacity || Number.MAX_VALUE;
  this.data = {};
  this.hash = {};
  this.linkedList = {
    length: 0,
    head: null,
    end: null
  }
  if (capacity <= 0) this.capacity = Number.MAX_VALUE;
};
CacheLRU.prototype.get = function(key) {
  key = &#39;_&#39; + key;
  var lruEntry = this.hash[key];
  if (!lruEntry) return;
  refresh(this.linkedList, lruEntry);
  return JSON.parse(this.data[key].toString());
};
CacheLRU.prototype.put = function(key, value) {
  key = &#39;_&#39; + key;
  var lruEntry = this.hash[key];
  if (value === undefined) return this;
  if (!lruEntry) {
    this.hash[key] = {key: key};
    this.linkedList.length += 1;
    lruEntry = this.hash[key];
  }
  refresh(this.linkedList, lruEntry);
  this.data[key] = new Buffer(JSON.stringify(value));
  if (this.linkedList.length > this.capacity) this.remove(this.linkedList.end.key.slice(1));
  return this;
};
CacheLRU.prototype.remove = function(key) {
  key = &#39;_&#39; + key;
  var lruEntry = this.hash[key];
  if (!lruEntry) return this;
  if (lruEntry === this.linkedList.head) this.linkedList.head = lruEntry.p;
  if (lruEntry === this.linkedList.end) this.linkedList.end = lruEntry.n;
  link(lruEntry.n, lruEntry.p);
  delete this.hash[key];
  delete this.data[key];
  this.linkedList.length -= 1;
  return this;
};
CacheLRU.prototype.removeAll = function() {
  this.data = {};
  this.hash = {};
  this.linkedList = {
    length: 0,
    head: null,
    end: null
  }
  return this;
};
CacheLRU.prototype.info = function() {
  var size = 0,
    data = this.linkedList.head;
  while (data){
    size += this.data[data.key].length;
    data = data.p;
  }
  return {
    capacity: this.capacity,
    length: this.linkedList.length,
    size: size
  };
};
// 更新链表,把get或put方法操作的key提到链表head,即表示最新
function refresh(linkedList, entry) {
  if (entry != linkedList.head) {
    if (!linkedList.end) {
      linkedList.end = entry;
    } else if (linkedList.end == entry) {
      linkedList.end = entry.n;
    }
    link(entry.n, entry.p);
    link(entry, linkedList.head);
    linkedList.head = entry;
    linkedList.head.n = null;
  }
}
// 对两个链表对象建立链接,形成一条链
function link(nextEntry, prevEntry) {
  if (nextEntry != prevEntry) {
    if (nextEntry) nextEntry.p = prevEntry;
    if (prevEntry) prevEntry.n = nextEntry;
  }
}
module.exports = CacheLRU;
// test:
/*var user = new CacheLRU(5);
user.put(&#39;user1&#39;, {name:&#39;admin&#39;, age: 30});
user.put(&#39;user2&#39;, {name:&#39;user&#39;, age: 31});
user.put(&#39;user3&#39;, {name:&#39;guest&#39;, age: 32});
user.put(&#39;user4&#39;, {name:&#39;guest&#39;, age: 34});
user.put(&#39;user5&#39;, {name:&#39;guest&#39;, age: 35});
console.log(user.get(&#39;user1&#39;));
console.log(user.get(&#39;user2&#39;));
console.log(user.get(&#39;user3&#39;));
user.put(&#39;user6&#39;, {name:&#39;guest&#39;, age: 36});
console.log(user.info());*/

LRU演算法也可以用於一些實際的應用程式中,如你要做一個瀏覽器,或類似淘寶客戶端的應用的就要用到這個原理。大家都知道瀏覽器在瀏覽網頁的時候會把下載的圖片暫時保存在本機的一個資料夾裡,下次再造訪時就會,直接從本機臨時資料夾裡讀取。但保存圖片的臨時資料夾是有一定容量限制的,如果你瀏覽的網頁太多,就會一些你最不常使用的圖像刪除掉,只保留最近最久使用的一些圖片。這時就可以用到LRU演算法了,這時上面演算法裡的這個特殊的堆疊就不是保存頁面的序號了,而是每個圖片的序號或大小;所以上面這個堆疊的元素都用

Object類別

來表示,這樣的話這個堆疊就可以保存的物件了。

以上是詳解Nodejs基於LRU演算法實作的快取處理操作方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn