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基于urllib实现按照百度音乐分类下载mp3的方法
May 25 Python
对Python的Django框架中的项目进行单元测试的方法
Apr 11 Python
在python下读取并展示raw格式的图片实例
Jan 24 Python
python3正则提取字符串里的中文实例
Jan 31 Python
Python3 批量扫描端口的例子
Jul 25 Python
基于python的列表list和集合set操作
Nov 24 Python
python jenkins 打包构建代码的示例代码
Nov 29 Python
python return逻辑判断表达式实现解析
Dec 02 Python
python序列类型种类详解
Feb 26 Python
tensorflow安装成功import tensorflow 出现问题
Apr 16 Python
如何理解python中数字列表
May 29 Python
浅析python连接数据库的重要事项
Feb 22 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
smarty 原来也不过如此~~呵呵
2006/11/25 PHP
PHP中空字符串介绍0、null、empty和false之间的关系
2012/09/25 PHP
[原创]PHP实现逐行删除文件右侧空格的方法
2015/12/25 PHP
PHP实现基于3DES算法加密解密字符串示例
2018/08/24 PHP
javascript实现的距离现在多长时间后的一个格式化的日期
2009/10/29 Javascript
ASP中进行HTML数据及JS数据编码函数
2009/11/11 Javascript
fancybox modal的完美解决(右上的X)
2012/10/30 Javascript
js multiple全选与取消全选实现代码
2012/12/04 Javascript
Jquery和angularjs获取check框选中的值的方法汇总
2016/01/17 Javascript
使用npm安装最新版本nodejs
2018/01/18 NodeJs
js变量声明var使用与不使用的区别详解
2019/01/21 Javascript
vue swipe自定义组件实现轮播效果
2019/07/03 Javascript
JS组件库AlloyTouch实现图片轮播过程解析
2020/05/29 Javascript
js实现点击选项置顶动画效果
2020/08/25 Javascript
Python中的jquery PyQuery库使用小结
2014/05/13 Python
Python字符串逆序输出的实例讲解
2019/02/16 Python
Python使用正则表达式分割字符串的实现方法
2019/07/16 Python
Python编写通讯录通过数据库存储实现模糊查询功能
2019/07/18 Python
python画蝴蝶曲线图的实例
2019/11/21 Python
python图形开发GUI库wxpython使用方法详解
2020/02/14 Python
Django框架静态文件处理、中间件、上传文件操作实例详解
2020/02/29 Python
Jupyter安装拓展nbextensions及解决官网下载慢的问题
2021/03/03 Python
浅谈CSS3 box-sizing 属性 有趣的盒模型
2019/04/02 HTML / CSS
HTML5 Canvas渐进填充与透明实现图像的Mask效果
2013/07/11 HTML / CSS
番木瓜健康和保健产品第一大制造商:Herbal Papaya
2017/04/25 全球购物
日本化妆品植村秀俄罗斯官方网站:Shu Uemura俄罗斯
2020/02/01 全球购物
怎样声明接口
2014/09/19 面试题
竞选演讲稿范文
2013/12/28 职场文书
党员政治学习材料
2014/05/14 职场文书
2014年党员整改措施
2014/10/24 职场文书
大班下学期个人总结
2015/02/13 职场文书
护士自荐信怎么写
2015/03/06 职场文书
初中思想品德教学反思
2016/02/24 职场文书
《哪吒之魔童降世》观后感:世上哪有随随便便的成功
2019/11/08 职场文书
ORACLE查看当前账号的相关信息
2021/06/18 Oracle
vmware虚拟机打不开vmx文件怎么办 ?vmware虚拟机vmx文件打开方法
2022/04/08 数码科技