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中pycurl库的用法实例
Sep 30 Python
Python Queue模块详解
Nov 30 Python
python获取本地计算机名字的方法
Apr 29 Python
python制作最美应用的爬虫
Oct 28 Python
总结网络IO模型与select模型的Python实例讲解
Jun 27 Python
python 3.6 +pyMysql 操作mysql数据库(实例讲解)
Dec 20 Python
Python实现端口检测的方法
Jul 24 Python
python 处理string到hex脚本的方法
Oct 26 Python
python重试装饰器的简单实现方法
Jan 31 Python
python使用装饰器作日志处理的方法
Jul 11 Python
pytorch实现查看当前学习率
Jun 24 Python
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
谏山创故乡大分县日田市水坝将设立《进击的巨人》立艾伦、三笠以及阿尔敏的铜像!
2020/03/06 日漫
php调整gif动画图片尺寸示例代码分享
2013/12/05 PHP
PHP读取RSS(Feed)简单实例
2014/06/12 PHP
php中解析带中文字符的url函数分享
2015/01/20 PHP
PHP-FPM 设置多pool及配置文件重写操作示例
2019/10/02 PHP
关于PhpStorm设置点击编辑文件自动定位源文件的实现方式
2020/12/30 PHP
extjs 学习笔记 四 带分页的grid
2009/10/20 Javascript
JavaScript的document对象和window对象详解
2010/12/30 Javascript
JS对外部文件的加载及对IFRMAME的加载的实现,当加载完成后,指定指向方法(方法回调)
2011/07/04 Javascript
js向上无缝滚动,网站公告效果 具体代码
2013/11/18 Javascript
jquery插件之定时查询待处理任务数量
2014/05/01 Javascript
node.js实现多图片上传实例
2014/06/03 Javascript
简单方法判断JavaScript对象为null或者属性为空
2014/09/26 Javascript
JavaScript使用指针操作实现约瑟夫问题实例
2015/04/07 Javascript
JavaScript encodeURI 和encodeURIComponent
2015/12/04 Javascript
Bootstrap源码解读媒体对象、列表组和面板(10)
2016/12/26 Javascript
详解require.js配置路径的用法和css的引入
2017/09/06 Javascript
详解angular笔记路由之angular-router
2017/09/12 Javascript
微信小程序实现传参数的几种方法示例
2018/01/10 Javascript
Vue.js 使用v-cloak后仍显示变量的解决方法
2018/11/19 Javascript
微信小程序实现时间预约功能
2018/11/27 Javascript
ES6 对象的新功能与解构赋值介绍
2019/02/05 Javascript
vue 输入电话号码自动按3-4-4分割功能的实现代码
2020/04/30 Javascript
使用python加密自己的密码
2015/08/04 Python
详解python3百度指数抓取实例
2016/12/12 Python
200 行python 代码实现 2048 游戏
2018/01/12 Python
Python八大常见排序算法定义、实现及时间消耗效率分析
2018/04/27 Python
python爬取网页转换为PDF文件
2018/06/07 Python
Python函数的参数常见分类与用法实例详解
2019/03/30 Python
Python实现的删除重复文件或图片功能示例【去重】
2019/04/23 Python
python使用 zip 同时迭代多个序列示例
2019/07/06 Python
计算机个人求职信范例
2014/01/24 职场文书
就业推荐表自我鉴定
2014/03/21 职场文书
MySQL数据库如何使用Shell进行连接
2022/04/12 MySQL
win10如何更改appdata文件夹的默认位置?
2022/07/15 数码科技
使用python生成大量数据写入es数据库并查询操作(2)
2022/09/23 Python