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 13 Python
Python通过Django实现用户注册和邮箱验证功能代码
Dec 11 Python
Pandas 对Dataframe结构排序的实现方法
Apr 10 Python
TensorFlow实现非线性支持向量机的实现方法
Apr 28 Python
python实现括号匹配的思路详解
Aug 23 Python
纯用NumPy实现神经网络的示例代码
Oct 24 Python
python字符串替换第一个字符串的方法
Jun 26 Python
Django框架组成结构、基本概念与文件功能分析
Jul 30 Python
Python Web框架之Django框架文件上传功能详解
Aug 16 Python
计算Python Numpy向量之间的欧氏距离实例
May 22 Python
Django mysqlclient安装和使用详解
Sep 17 Python
python和C/C++混合编程之使用ctypes调用 C/C++的dll
Apr 29 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开发过程中常用函数收藏
2009/12/14 PHP
Laravel 4 初级教程之Pages、表单验证
2014/10/30 PHP
Thinkphp搭建包括JS多语言的多语言项目实现方法
2014/11/24 PHP
[原创]smarty简单模板变量输出方法
2016/07/09 PHP
php+redis在实际项目中HTTP 500: Internal Server Error故障排除
2017/02/05 PHP
PHP Ajax跨域问题解决方案代码实例
2020/08/01 PHP
PHP http请求超时问题解决方案
2020/11/13 PHP
xtree.js 代码
2007/03/13 Javascript
Wordpress ThickBox 添加“查看原图”效果代码
2010/12/11 Javascript
用JavaScript获取DOM元素位置和尺寸大小的方法
2013/04/12 Javascript
使用js判断TextBox控件值改变然后出发事件
2014/03/07 Javascript
php析构函数的具体用法小结
2014/03/11 Javascript
JavaScript:Date类型全面解析
2016/05/19 Javascript
JQuery之proxy实现绑定代理方法
2016/08/01 Javascript
使用JS实现图片展示瀑布流效果(简单实例)
2016/09/06 Javascript
使用JSON作为函数的参数的优缺点
2016/10/27 Javascript
jQuery Validate验证表单时多个name相同的元素只验证第一个的解决方法
2016/12/24 Javascript
详解前端构建工具gulpjs的使用介绍及技巧
2017/01/19 Javascript
利用jquery去掉时光轴头尾部线条的方法实例
2017/06/16 jQuery
JavaScript模拟文件拖选框样式v1.0的实例
2017/08/04 Javascript
React Native中TabBarIOS的简单使用方法示例
2017/10/13 Javascript
简单实现jquery隔行变色
2017/11/09 jQuery
利用vscode调试编译后的js代码详解
2018/05/14 Javascript
JavaScript设计模式之装饰者模式定义与应用示例
2018/07/25 Javascript
ElementUI Tree 树形控件的使用并给节点添加图标
2020/02/27 Javascript
Python中实现结构相似的函数调用方法
2015/03/10 Python
Python之读取TXT文件的方法小结
2018/04/27 Python
Python eval的常见错误封装及利用原理详解
2019/03/26 Python
Python字符串的常见操作实例小结
2019/04/08 Python
使用Keras训练好的.h5模型来测试一个实例
2020/07/06 Python
django filter过滤器实现显示某个类型指定字段不同值方式
2020/07/16 Python
HTML5中的音频和视频媒体播放元素小结
2016/01/29 HTML / CSS
Hawes & Curtis澳大利亚官网:英国经典服饰品牌
2018/10/29 全球购物
铣工实训报告
2014/11/05 职场文书
安全教育日主题班会
2015/08/13 职场文书
Golang并发操作中常见的读写锁详析
2021/08/30 Golang