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实现的一个简单LRU cache
Sep 26 Python
Django静态资源URL STATIC_ROOT的配置方法
Nov 08 Python
python利用OpenCV2实现人脸检测
Apr 16 Python
对Tensorflow中的矩阵运算函数详解
Jul 27 Python
Python 中导入csv数据的三种方法
Nov 01 Python
浅谈Python编程中3个常用的数据结构和算法
Apr 30 Python
在pyqt5中QLineEdit里面的内容回车发送的实例
Jun 21 Python
利用python实现汉字转拼音的2种方法
Aug 12 Python
python运用pygame库实现双人弹球小游戏
Nov 25 Python
python爬虫模拟浏览器访问-User-Agent过程解析
Dec 28 Python
Django数据库操作之save与update的使用
Apr 01 Python
Selenium及python实现滚动操作多种方法
Jul 21 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/03 咖啡文化
WordPress中用于获取文章信息以及分类链接的函数用法
2015/12/18 PHP
PHP 搜索查询功能实现
2016/11/29 PHP
详解PHP变量传值赋值和引用赋值变量销毁
2019/03/23 PHP
javascript date格式化示例
2013/09/25 Javascript
巧用js提交表单轻松解决一个页面有多个提交按钮
2013/11/17 Javascript
jQuery中has()方法用法实例
2015/01/06 Javascript
jquery+javascript编写国籍控件
2015/02/12 Javascript
浅谈javascript中的DOM方法
2015/07/16 Javascript
微信小程序(应用号)简单实例应用及实例详解
2016/09/26 Javascript
百度多文件异步上传控件webuploader基本用法解析
2016/11/07 Javascript
easyUI实现类似搜索框关键词自动提示功能示例代码
2016/12/27 Javascript
addeventlistener监听scroll跟touch(实例讲解)
2017/08/04 Javascript
原生JS写Ajax的请求函数功能
2017/12/22 Javascript
javascript 易错知识点实例小结
2020/04/25 Javascript
[01:20:47]DOTA2-DPC中国联赛 正赛 Ehome vs Magma BO3 第一场 1月19日
2021/03/11 DOTA
[01:19:46]DOTA2-DPC中国联赛 正赛 SAG vs DLG BO3 第一场 2月28日
2021/03/11 DOTA
深入理解Python单元测试unittest的使用示例
2017/11/18 Python
对python-3-print重定向输出的几种方法总结
2018/05/11 Python
Python根据成绩分析系统浅析
2019/02/11 Python
Python使用reportlab模块生成PDF格式的文档
2019/03/11 Python
Python3网络爬虫开发实战之极验滑动验证码的识别
2019/08/02 Python
Flask框架学习笔记之模板操作实例详解
2019/08/15 Python
Python栈的实现方法示例【列表、单链表】
2020/02/22 Python
Python脚本去除文件的只读性操作
2020/03/05 Python
地图可视化神器kepler.gl python接口的使用方法
2020/12/22 Python
HTML5中使用postMessage实现Ajax跨域请求的方法
2016/04/19 HTML / CSS
html5定位并在百度地图上显示的示例
2014/04/27 HTML / CSS
美国第一大药店连锁机构:Walgreens(沃尔格林)
2019/10/10 全球购物
Linux中如何用命令创建目录
2016/12/02 面试题
销售简历自我评价
2014/01/24 职场文书
求职自我评价范文100字
2014/09/23 职场文书
病危通知单
2015/04/17 职场文书
八年级数学教学反思
2016/02/17 职场文书
解决python存数据库速度太慢的问题
2021/04/23 Python
JUnit5常用注解的使用
2021/07/02 Java/Android