Python實現(xiàn)的一個簡單LRU cache
起因:我的同事需要一個固定大小的cache,如果記錄在cache中,直接從cache中讀取,否則從數(shù)據(jù)庫中讀取。python的dict 是一個非常簡單的cache,但是由于數(shù)據(jù)量很大,內(nèi)存很可能增長的過大,因此需要限定記錄數(shù),并用LRU算法丟棄舊記錄。key 是整型,value是10KB左右的python對象
分析:
1)可以想到,在對于cache,我們需要維護(hù) key -> value 的關(guān)系
2)而為了實現(xiàn)LRU,我們又需要一個基于時間的優(yōu)先級隊列,來維護(hù) timestamp -> (key, value) 的關(guān)系
3)當(dāng)cache 中的記錄數(shù)達(dá)到一個上界maxsize時,需要將timestamp 最小的(key,value) 出隊列
4) 當(dāng)一個(key, value) 被命中時,實際上我們需要將它從隊列中,移除并插入到隊列的尾部。
從分析可以看出我們的cache 要達(dá)到性能最優(yōu)需要滿足上面的四項功能,對于隊表的快速移除和插入,鏈表顯然是最優(yōu)的選擇,為了快速移除,最好使用雙向鏈表,為了插入尾部,需要有指向尾部的指針。
下面用python 來實現(xiàn):
#encoding=utf-8
class LRUCache(object):
def __init__(self, maxsize):
# cache 的最大記錄數(shù)
self.maxsize = maxsize
# 用于真實的存儲數(shù)據(jù)
self.inner_dd = {}
# 鏈表-頭指針
self.head = None
# 鏈表-尾指針
self.tail = None
def set(self, key, value):
# 達(dá)到指定大小
if len(self.inner_dd) >= self.maxsize:
self.remove_head_node()
node = Node()
node.data = (key, value)
self.insert_to_tail(node)
self.inner_dd[key] = node
def insert_to_tail(self, node):
if self.tail is None:
self.tail = node
self.head = node
else:
self.tail.next = node
node.pre = self.tail
self.tail = node
def remove_head_node(self):
node = self.head
del self.inner_dd[node.data[0]]
node = None
self.head = self.head.next
self.head.pre = None
def get(self, key):
if key in self.inner_dd:
# 如果命中, 需要將對應(yīng)的節(jié)點移動到隊列的尾部
node = self.inner_dd.get(key)
self.move_to_tail(node)
return node.data[1]
return None
def move_to_tail(self, node):
# 只需處理在隊列頭部和中間的情況
if not (node == self.tail):
if node == self.head:
self.head = node.next
self.head.pre = None
self.tail.next = node
node.pre = self.tail
node.next = None
self.tail = node
else:
pre_node = node.pre
next_node = node.next
pre_node.next = next_node
next_node.pre = pre_node
self.tail.next = node
node.pre = self.tail
node.next = None
self.tail = node
class Node(object):
def __init__(self):
self.pre = None
self.next = None
# (key, value)
self.data = None
def __eq__(self, other):
if self.data[0] == other.data[0]:
return True
return False
def __str__(self):
return str(self.data)
if __name__ == '__main__':
cache = LRUCache(10)
for i in xrange(1000):
cache.set(i, i+1)
cache.get(2)
for key in cache.inner_dd:
print key, cache.inner_dd[key]
相關(guān)文章
16行Python代碼實現(xiàn)微信聊天機(jī)器人并自動智能回復(fù)功能
聊天機(jī)器人自動智能回復(fù)給我們的生活帶來了極大的便利,尤其在業(yè)務(wù)比較繁忙的時候,智能機(jī)器人給我們帶來極大的方便,今天小編教大家一招通過16行代碼實現(xiàn)微信聊天智能機(jī)器人,感興趣的朋友一起看看吧2022-01-01python 爬蟲一鍵爬取 淘寶天貓寶貝頁面主圖顏色圖和詳情圖的教程
今天小編就為大家分享一篇python 爬蟲一鍵爬取 淘寶天貓寶貝頁面主圖顏色圖和詳情圖的教程,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-05-05pandas如何將datetime64[ns]轉(zhuǎn)為字符串日期
這篇文章主要介紹了pandas如何將datetime64[ns]轉(zhuǎn)為字符串日期,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07python實現(xiàn)mask矩陣示例(根據(jù)列表所給元素)
這篇文章主要介紹了python實現(xiàn)mask矩陣示例(根據(jù)列表所給元素),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07