Python实现的一个简单LRU cache
起因:我的同事需要一个固定大小的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 来实现:
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实现的一个简单LRU cache的更多相关文章
- python定义的一个简单的shell函数的代码
把写代码过程中经常用到的一些代码段做个记录,如下代码段是关于python定义的一个简单的shell函数的代码. pipe = subprocess.Popen(cmd, stdout=subproce ...
- Windows 下针对python脚本做一个简单的进程保护
前提: 大家运行的脚本程序经常会碰到系统异常关闭.或被其他用户错杀的情况.这样就需要一个进程保护的工具. 本文结合windows 的计划任务,实现一个简单的进程保护的功能. 利用py2exe生产 ex ...
- Python学习 - 编写一个简单的web框架(二)
在上一篇日志中已经讨论和实现了根据url执行相应应用,在我阅读了bottle.py官方文档后,按照bottle的设计重写一遍,主要借鉴大牛们的设计思想. 一个bottle.py的简单实例 来看看bot ...
- python实现的一个简单的网页爬虫
学习了下python,看了一个简单的网页爬虫:http://www.cnblogs.com/fnng/p/3576154.html 自己实现了一个简单的网页爬虫,获取豆瓣的最新电影信息. 爬虫主要是获 ...
- Flask学习之旅--用 Python + Flask 制作一个简单的验证码系统
一.写在前面 现在无论大大小小的网站,基本上都会使用验证码,登录的时候要验证,下载的时候要验证,而使用的验证码也从那些简简单单的字符图形验证码“进化”成了需要进行图文识别的验证码.需要拖动滑块的滑动验 ...
- Python并发编程-一个简单的爬虫
一个简单的爬虫 #网页状态码 #200 正常 #404 网页找不到 #502 504 import requests from multiprocessing import Pool def get( ...
- Python学习 - 编写一个简单的web框架(一)
自己动手写一个web框架,因为我是菜鸟,对于python的一些内建函数不是清楚,所以在写这篇文章之前需要一些python和WSGI的预备知识,这是一系列文章.这一篇只实现了如何处理url. 参考这篇文 ...
- 使用Python来编写一个简单的感知机
来表示.第二个元素是表示期望输出的值. 这个数组定义例如以下: training_data = [ (array([0,0,1]), 0), (array([0,1,1]), 1), (arra ...
- 利用python+tkinter做一个简单的智能电视遥控器
要通过python实现遥控器功能分两步: 第一步:开发图形化界面,以暴风TV的遥控器按钮为例 第二步:使PC端给电视发送相应指令(此步骤需要打开电视的adb开关) 现在就开始第一步操作实现遥控器功能, ...
随机推荐
- Ajax向前后台传递json和转换
学生管理系统MVC模式设计心得: jquery .ajax提交data数据格式 jquery 的Ajax方法提交数据,但是是多个参数,具体data的格式如下: data提交的数据类型为:Object ...
- Spring实战Day5
3.3自动装配bean的歧义性 产生歧义的原因 找到多个符合条件的组件,如下注入talent时会有两个满足条件的组件 解决方法 标示首选的bean,但是同时标示两个或多个同样会存在歧义 自动装配标示P ...
- 转:Linux字符编码方式
首先,解释一下字符集: 汉字编码: * GB2312字集是简体字集,全称为GB2312(80)字集,共包括国标简体汉字6763个. * BIG5字集是台湾繁体字集,共包括国标繁体汉字13053个. * ...
- Maven自动部署(SCM-SVN/Git)(maven-scm-plugin/maven-release-plugin插件的使用)
以下内容引用自https://ayayui.gitbooks.io/tutorialspoint-maven/content/book/maven_deployment_automation.html ...
- android开发教程之使用线程实现视图平滑滚动示例 改
package com.melonsapp.messenger.ui.popupuser; import android.os.Handler; import android.view.View; i ...
- git-flow 工作流 备忘清单
关于 git-flow 是一个 git 扩展集,按 Vincent Driessen 的分支模型提供高层次的库操作. 查看详情 ★ ★ ★ 这个备忘清单展示了 git-flow 的基本操作和效果. ★ ...
- 基于MNIST数据的softmax regression
跟着tensorflow上mnist基本机器学习教程联系 首先了解sklearn接口: sklearn.linear_model.LogisticRegression In the multiclas ...
- 使用nginx转发不了静态文件
从django runserver的请求来看,都收不到静态文件请求, 查看firefox的web console请求,发现都是403 然后发现nginx不在当前用户组,并且当前用户的项目的读写权限是7 ...
- start memcached
memcached -m 64 -p 11211 -u fly -l 127.0.0.1 ------------------------------------------------------- ...
- java开始到熟悉66-69
本次内容:DateFormat类 1.DateFormat类 package array; /** * 时间和字符串之间的转化 */ import java.text.DateFormat; impo ...