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查找目录下指定扩展名的文件实例
Apr 01 Python
python中list列表的高级函数
May 17 Python
python 格式化输出百分号的方法
Jan 20 Python
Python3模拟curl发送post请求操作示例
May 03 Python
python mqtt 客户端的实现代码实例
Sep 25 Python
python多进程(加入进程池)操作常见案例
Oct 21 Python
python实现随机加减法生成器
Feb 24 Python
基于python实现FTP文件上传与下载操作(ftp&sftp协议)
Apr 01 Python
pytorch 中的重要模块化接口nn.Module的使用
Apr 02 Python
详细分析Python可变对象和不可变对象
Jul 09 Python
Python如何使用ElementTree解析xml
Oct 12 Python
如何用python 操作zookeeper
Dec 28 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
PHP生成自适应大小的缩略图类及使用方法分享
2014/05/06 PHP
深入浅析PHP7.0新特征(五大新特征)
2015/10/29 PHP
jQuery使用手册之二 DOM操作
2007/03/24 Javascript
jQuery getJSON 处理json数据的代码
2010/07/26 Javascript
网站页面自动跳转实现方法PHP、JSP(上)
2010/08/01 Javascript
javascipt基础内容--需要注意的细节
2013/04/10 Javascript
JS连连看源码完美注释版(推荐)
2013/12/09 Javascript
jQuery实现html表格动态添加新行的方法
2015/05/28 Javascript
jQuery鼠标经过方形图片切换成圆边效果代码分享
2015/08/20 Javascript
javascript与jquery动态创建html元素示例
2016/07/25 Javascript
在windows上用nodejs搭建静态文件服务器的简单方法
2016/08/11 NodeJs
CSS3 3D 技术手把手教你玩转
2016/09/02 Javascript
微信小程序 使用picker封装省市区三级联动实例代码
2016/10/28 Javascript
Vue指令的钩子函数使用方法
2017/03/20 Javascript
jQuery查找dom的几种方法效率详解
2017/05/17 jQuery
解决ionic和angular上拉加载的问题
2017/08/03 Javascript
js实时监控文本框输入字数的实例代码
2018/01/18 Javascript
jQuery实现的简单对话框拖动功能示例
2018/06/05 jQuery
JavaScript引用类型之基本包装类型实例分析【Boolean、Number和String】
2018/08/09 Javascript
详解javascript replace高级用法
2019/02/17 Javascript
TypeScript中使用getElementXXX()的示例代码
2019/09/12 Javascript
python批量生成本地ip地址的方法
2015/03/23 Python
Python+Opencv识别两张相似图片
2020/03/23 Python
Python+MongoDB自增键值的简单实现
2016/11/04 Python
pandas.DataFrame选取/排除特定行的方法
2018/07/03 Python
解决Pycharm调用Turtle时 窗口一闪而过的问题
2019/02/16 Python
Django利用cookie保存用户登录信息的简单实现方法
2019/05/27 Python
python爬虫 urllib模块反爬虫机制UA详解
2019/08/20 Python
Python中url标签使用知识点总结
2020/01/16 Python
查询优化的一般准则有哪些
2015/03/08 面试题
材料会计岗位职责
2014/03/06 职场文书
班主任经验交流会主持词
2014/04/01 职场文书
2014最新开业庆典策划方案(5篇)
2014/09/15 职场文书
村党组织公开承诺书
2015/04/30 职场文书
培训简讯范文
2015/07/20 职场文书
POST提交数据常见的四种方式
2022/01/18 HTML / CSS