Python实现的一个简单LRU cache


Posted in Python onSeptember 26, 2014

起因:我的同事需要一个固定大小的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]
Python 相关文章推荐
python 快速排序代码
Nov 23 Python
python字典键值对的添加和遍历方法
Sep 11 Python
python版本坑:md5例子(python2与python3中md5区别)
Jun 20 Python
Python基于time模块求程序运行时间的方法
Sep 18 Python
Python中 传递值 和 传递引用 的区别解析
Feb 22 Python
教你使用python画一朵花送女朋友
Mar 29 Python
Python3中编码与解码之Unicode与bytes的讲解
Feb 28 Python
Python中一个for循环循环多个变量的示例
Jul 16 Python
django框架使用方法详解
Jul 18 Python
Python基础之函数基本用法与进阶详解
Jan 02 Python
详解pycharm连接远程linux服务器的虚拟环境的方法
Nov 13 Python
解决pip安装tensorflow中出现的no module named tensorflow.python 问题方法
Feb 20 Python
python网络编程实例简析
Sep 26 #Python
python的re模块应用实例
Sep 26 #Python
python实现自动登录人人网并访问最近来访者实例
Sep 26 #Python
编程语言Python的发展史
Sep 26 #Python
python人人网登录应用实例
Sep 26 #Python
python快速查找算法应用实例
Sep 26 #Python
python求众数问题实例
Sep 26 #Python
You might like
收音机鉴频器对声音的影响和频偏分析
2021/03/02 无线电
提升PHP执行速度全攻略(下)
2006/10/09 PHP
PHP小程序自动提交到自助友情连接
2009/11/24 PHP
PHP实现根据密码长度显示安全条
2017/07/04 PHP
JavaScript中__proto__与prototype的关系深入理解
2012/12/04 Javascript
JQuery+DIV自定义滚动条样式的具体实现
2013/06/25 Javascript
javascript轻量级模板引擎juicer使用指南
2014/06/22 Javascript
javascript实现dom动态创建省市纵向列表菜单的方法
2015/05/14 Javascript
javascript实现textarea中tab键的缩排处理方法
2015/06/26 Javascript
localStorage的黑科技-js和css缓存机制
2017/02/06 Javascript
浅谈vue路径优化之resolve
2017/10/13 Javascript
vue mint-ui tabbar变组件使用
2018/05/04 Javascript
微信小程序简单的canvas裁剪图片功能详解
2019/07/12 Javascript
JavaScript如何借用构造函数继承
2019/11/06 Javascript
Vue项目中数据的深度监听或对象属性的监听实例
2020/07/17 Javascript
python学习笔记之调用eval函数出现invalid syntax错误问题
2015/10/18 Python
Python 专题一 函数的基础知识
2017/03/16 Python
python3 shelve模块的详解
2017/07/08 Python
python绘制立方体的方法
2018/07/02 Python
用python的turtle模块实现给女票画个小心心
2019/11/23 Python
Python itertools.product方法代码实例
2020/03/27 Python
Python 抓取数据存储到Redis中的操作
2020/07/16 Python
树莓派4B安装Tensorflow的方法步骤
2020/07/16 Python
python中np是做什么的
2020/07/21 Python
通过一张图教会你CSS3倒影的实现
2017/09/26 HTML / CSS
匡威帆布鞋美国官网:Converse美国
2016/08/22 全球购物
领先的荷兰线上超市:荷兰之家Holland at Home(支持中文)
2021/01/21 全球购物
教师队伍管理制度
2014/01/14 职场文书
幼儿园教师国培感言
2014/02/02 职场文书
趣味运动会活动方案
2014/02/12 职场文书
护士求职信
2014/07/05 职场文书
老舍《猫》教学反思
2016/02/17 职场文书
曾国藩励志经典名言37句,蕴含哲理
2019/10/14 职场文书
PyCharm配置KBEngine快速处理代码提示冲突、配置命令问题
2021/04/03 Python
如何在python中实现ECDSA你知道吗
2021/11/23 Python
HTML页面中使两个div并排显示的实现
2022/05/15 HTML / CSS