Python 中怎么来实现类似 Cache 的功能

cachetools,这是一个可扩展的基于内存的 collections、decorators 的封装实现。
因为是 cache,那么就一定有它的页面置换算法。根据操作系统学过的一些知识,置换算法就会有 lru、lfu、fifo 等等。比如说,当 cache 已经满了的情况下,如果这时候再插入一个新的数据,那么这时候就需要根据页面置换算法对已有的数据进行置换,用新的数据替代旧的数据,保证 cache 最大占用量不会超标。
废话不多说了,这里我们来体验下这个库的具体用法吧。
首先是安装,直接使用 pip3 安装即可:
pip3 install cachetools安装好之后,我们再来看看它的具体用法。
基本 cache 的使用我们来看一个简单的实例:
from cachetools import cachecache = cache(maxsize=3)cache['1'] = 'hello'cache['2'] = 'world'print('current size', cache.currsize)cache.pop('2')print(cache.items)print('length', len(cache))cache['3'] = 'hello'cache['4'] = 'world'print('current size', cache.currsize)cache['5'] = 'hello'print('current size', cache.currsize)print(cache.items)运行结果如下:
current size 2length 1current size 3current size 3首先这里声明了一个 cache 对象,有一个必传的参数是 maxsize,这里设置为 3,这里的 3 其实就是长度的意思,并不是实际内存占用大小。
接着我们赋值了 1 和 2 两个键名,接着打印出来了当前 cache 的大小,所以结果就是 2,这个 size 就是一个单纯的数量值。
然后接着调用了 pop 方法移除了 2 对应的内容,然后打印 cache 的所有内容和对应长度,理所应当,长度就是 2,然后就剩下一个值。
接着我们又赋值了 3 和 4 两个键名,然后打印了当前 cache 的大小,这会 cache 达到了 maxsize,结果就是 3。
最后我们又赋值了 5 这个键名,然后打印了当前 cache 的大小和 cache 的所有内容,因为 cache 已经达到了 maxsize 了,所以结果依然是 3,最前面的 1 这个键名对应的内容就被移除了。
所以,这个 cache 对象可以维持一个最大恒定大小,并且保证长度不会超过 maxsize。
其他 cache 的使用当然除了 cache,还有一些 cache 的子类,比如说 fifocache、lfucahce、lrucache、mrucache、rrcache,这里简单说下:
fifo:first in、first out,就是先进先出。lfu:least frequently used,就是淘汰最不常用的。lru:least recently used,就是淘汰最久不用的。mru:most recently used,与 lru 相反,淘汰最近用的。rr:random replacement,就是随机替换。具体的实例这里就不再讲解了。
特殊 ttlcache 的使用当然除了基本的 cache,cachetools 还提供了一种特殊的 cache 实现,叫做 ttlcache。
ttl 就是 time-to-live 的简称,也就是说,cache 中的每个元素都是有过期时间的,如果超过了这个时间,那这个元素就会被自动销毁。如果都没过期并且 cache 已经满了的话,那就会采用 lru 置换算法来替换掉最久不用的,以此来保证数量。
下面我们来看一个样例:
from datetime import timedelta, datetimefrom cachetools import ttlcachefrom time import sleepcache = ttlcache(maxsize=3, ttl=timedelta(seconds=5), timer=datetime.now)cache['1'] = 'hello'sleep(1)cache['2'] = 'world'print(cache.items)sleep(4.5)print(cache.items)sleep(1)print(cache.items)运行结果如下:
这里我们声明了一个 ttlcache,maxsize 是 3,然后 ttl 设置为了 5 秒,也就是说,每个元素 5 秒之后都会过期。
首先我们赋值 1 这个键名为 hello,然后 1 秒之后赋值 2 这个键名为 world,接着将现有 cache 的结果输出出来。
接着等待 4.5 秒,这时候 1 这个键名就已经超过 5 秒了,所以 1 这个键名理应就被销毁了。
接着再等待 1 秒,这时候 2 这个键名也超过 5 秒了,所以 2 这个键名也理应就被销毁了。
最后看运行结果也如我们期望的一样。
大小计算有的同学说,你这里 maxsize 用的这个数字指的是内容的长度,但实际上不同的内容占用的空间是完全不一样的,有没有根据实际内存占用来计算 size 的方法呢?
有的!
这里我们只需要替换掉 cache 的 getsizeof 方法即可。
这里我们需要额外引入一个库,叫做 pympler,它提供了一个 asizeof 方法可以计算实际 object 的占用内存大小,单位是 bytes。
pympler 安装:
pip3 install pympler所以,如果我们要设置 cache 占用的最大内存大小,比如 2mb,那就可以这么设置:
from cachetools import cachefrom pympler import asizeofcache = cache(maxsize=2 * 1024 * 1024, getsizeof=asizeof.asizeof)cache['a'] = '123'print(cache.currsize)cache['b'] = '123'print(cache.currsize)cache['c'] = '456'print(cache.currsize)cache['d'] = { 'a': 'b', 'b': 'c', 'c': 'd'}print(cache.currsize)这里 maxsize 我们就设置为了 2mb,同时 getsizeof 方法设置为了 pympler 的 asizeof 方法,这样 cache 在计算 size 的时候就会用 asizeof 方法了。
这里我们随便插入一些数据,看看实际的 size 变化,运行结果如下:
56112168640其结果就是 cache 占用的字节数。可以看到数据的复杂度高,占用的空间越大。
更多好了,其实到现在为止,基本的 cache 和 ttlcache 就够我们使用了。

上海首颁载人测试牌照,自动驾驶企业还面临着多重考验
深度学习如何挑选GPU?
关于工业涂料—金属涂层的介绍和使用指南
科学家正研究用冰制造机器人
碱性蓄电池的常见故障和对策
Python 中怎么来实现类似 Cache 的功能
OPC UA FX是什么?优势及未来趋势全解析
NXP车载多设备无线充电解决方案
5G技术的发展如何协助智慧医疗的发展
常用电子元器件的识别
三星三季度预计下滑80%,2009年以来最低
华为官宣新服务,要彻底向安卓说再见
半导体行业资本逐鹿 芯片龙头英特尔锐势稍减
InAs/GaSb Ⅱ类超晶格红外探测器背减薄技术工作研究
浅谈喇叭防水透气膜(防水透声膜)特点有哪些
友尚推出基于瑞昱半导体技术的高整合度Hi-Fi耳机芯片级解决方案
5G与人工智能成为信息通信领域的两颗热门“双子星”
高成本效益的实用系统方法解决QFN-mr BiCMOS器件单元测试电源电流失效问题
ITECH发布交流电源、交流负载新升级产品
什么是背照式CMOS_背照式CMOS的优缺点