时间:2021-05-22
起因:我的同事需要一个固定大小的cache,如果记录在cache中,直接从cache中读取,否则从数据库中读取。python的dict 是一个非常简单的cache,但是由于数据量很大,内存很可能增长的过大,因此需要限定记录数,并用LRU算法丢弃旧记录。key 是整型,value是10KB左右的python对象
分析:
1)可以想到,在对于cache,我们需要维护 key -> value 的关系
2)而为了实现LRU,我们又需要一个基于时间的优先级队列,来维护 timestamp -> (key, value) 的关系
3)当cache 中的记录数达到一个上界maxsize时,需要将timestamp 最小的(key,value) 出队列
4) 当一个(key, value) 被命中时,实际上我们需要将它从队列中,移除并插入到队列的尾部。
从分析可以看出我们的cache 要达到性能最优需要满足上面的四项功能,对于队表的快速移除和插入,链表显然是最优的选择,为了快速移除,最好使用双向链表,为了插入尾部,需要有指向尾部的指针。
下面用python 来实现:
复制代码 代码如下:
#encoding=utf-8
class LRUCache(object):
def __init__(self, maxsize):
# cache 的最大记录数
self.maxsize = maxsize
# 用于真实的存储数据
self.inner_dd = {}
# 链表-头指针
self.head = None
# 链表-尾指针
self.tail = None
def set(self, key, value):
# 达到指定大小
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:
# 如果命中, 需要将对应的节点移动到队列的尾部
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]
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
今天我们会讲到一个[装饰器]注记:链接“装饰器”指Python3教程中的装饰器教程。可以在这里快速了解什么是装饰器。@functools.lru_cache——
Python的lru_cache装饰器是一个为自定义函数提供缓存功能的装饰器。其内部会在下次以相同参数调用该自定义函数时直接返回计算好的结果。通过缓存计算结果可
学了一个多月的python,做了一个小程序:python实现简单成绩录入系统,实验一下menu部分fromtkinterimport*#这是一个python模块
本文介绍了Vue2SSR缓存Api数据,分享给大家,具体如下:1.安装缓存依赖:lru-cachenpminstalllru-cache--dev2.api配置
本文实例讲述了Python实现简单状态框架的方法。分享给大家供大家参考。具体分析如下:这里使用Python实现一个简单的状态框架,代码需要在python3.2环