LFU緩存


 http://blog.sina.com.cn/s/blog_567842410100nf1g.html

Cache(高速緩存), 一個在計算機中幾乎隨時接觸的概念。CPU中Cache能極大提高存取數據和指令的時間,讓整個存儲器(Cache+內存)既有Cache的高速度,又能有內存的大容量;操作系統中的內存page中使用的Cache能使得頻繁讀取的內存磁盤文件較少的被置換出內存,從而提高訪問速度;數據庫中數據查詢也用到Cache來提高效率;即便是Powerbuilder的DataWindow數據處理也用到了Cache的類似設計。Cache的算法設計常見的有FIFO(first in first out)和LRU(least recently used),FIFO對CPU的指令序列非常有效,但更多的,對於Memory或者磁盤文件的這種Cache,LRU就更有效多了。FIFO的算法設計很簡單明瞭,就不做討論,在此只是對LRU展開。

Cache中的存儲空間被分成若干塊,每一塊對應內存或者磁盤文件的一段數據(當然也可以是指令數據),形成這種映射關係,當Cache中的存儲塊被用完,而需要把新的數據Load進Cache的時候,我們就需要設計一種良好的算法來完成數據塊的替換。LRU的思想是基於“最近用到的數據被重用的概率比較早用到的大的多”這個設計規則來實現的。Cache中的所有塊位置都用雙向鏈表鏈接起來,當一個位置被命中後,就將通過調整鏈表的指向將該位置調整到鏈表的頭位置,新加入的內容直接放在鏈表的頭上。這樣,在進行過多次查找操作後,最近被命中過的內容就向鏈表的頭移動,而沒有被命中的內容就向鏈表的後面移動。當需要替換時,鏈表最後的位置就是最近最少被命中的位置,我們只需要將新的內容放在鏈表前面,淘汰鏈表最後的位置就是想了。

對於雙向鏈表的使用,基於兩個考慮。首先是Cache中塊的命中可能是隨機的,和Load進來的順序無關,所以我們需要用鏈表這種結構來保存位置隊列,使得其可以靈活的調整相互間的次序。其次,雙向鏈表使得在知道一個位置的情況下可以很迅速的移到其他的地方,時間複雜度爲O(1)。

查找一個鏈表中元素的時間複雜度是O(n),每次命中的時候,我們就需要花費O(n)的時間來進行查找,如果不添加其他的數據結構,這個就是我們能實現的最高效率了。目前看來,整個算法的瓶頸就是在查找這裏了,怎麼樣才能提高查找的效率呢?Hash表,對,就是它,數據結構中之所以有它,就是因爲它的查找時間複雜度是O(1)。梳理一下思路:對於Cache的每個位置,我們設計一個數據結構來儲存Cache塊的內容,並實現一個雙向鏈表,其中屬性next和prev時雙向鏈表的兩個指針,key用於存儲對象的鍵值,value用戶存儲要cache塊對象本身,然後用Hash表來查找具體被命中的Cache塊。剩下的就是寫Code的事了:我們使用一個hashmap作爲cache,用hashmap的檢索機制來實現cache查找;並用head和last兩個屬性來記錄鏈表的頭和尾。並提供putEntry(),getEntry()方法來操作該cache。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章