对那些需要高频率以相同参数运行的函数,或者需要重复加载的数据,如果每次都执行函数完整的代码,或者重复从文件加载数据进行处理,会试程序运行效率变低。改善效率可通过使用内存缓存或磁盘缓存的形式,从而提高代码效率。
1 内存缓存 lru_cache
适用条件:函数经常需要以相同输入参数执行。
效果:以参数args执行函数时,如果内存缓存中记录了相同输入参数的运行结果,则函数直接从缓存中返回结果,不在执行函数体的代码。
举例:
import functools
SIZE_CACHE = 1 # 缓存大小
@functools.lru_cache(SIZE_CACHE)
def my_add(a, b):
print("函数体被执行")
return a+b
if __name__ == "__main__":
print("第一次运行结果。缓存为空,需要函数体")
print(my_add(1, 1), '\n')
print("第二次运行结果。由于缓存已有a=1,b=1的结果,所以函数体不执行")
print(my_add(1, 1), '\n')
print("第三次运行结果。缓存中没有a=1,b=2的结果,函数体要执行")
print(my_add(1, 2), '\n')
print("第四次运行结果。缓存中已变为a=1,b=2的结果,a=1,b=1的缓存已被覆盖,所以函数体执行")
print(my_add(1, 1), '\n')
运行结果:
第一次运行结果。缓存为空,需要函数体
函数体被执行
2
第二次运行结果。由于缓存已有a=1,b=1的结果,所以函数体不执行
2
第三次运行结果。缓存中没有a=1,b=2的结果,函数体要执行
函数体被执行
3
第四次运行结果。缓存中已变为a=1,b=2的结果,a=1,b=1的缓存已被覆盖,所以函数体执行
函数体被执行
2
2 磁盘缓存 diskcache
如果需要经常从文件读取数据进行预处理,可以将预处理结果存到磁盘缓存中,这样下次可直接读取磁盘缓存的结果,省去数据处理的实际。磁盘缓存有很多第三方库,其中一个为diskcache
适用条件:频发加载数据,比如机器学习加载数据集。
效果:可提高数据加载速度。
举例:
from diskcache import FanoutCache
import time
my_cache = FanoutCache(r"D:/my_cache",
shards=64, # 将缓存文件自动分成64个部分
timeout=1,
size_limit=3e11, # 每个部分文件的文件最大占用空间
# disk_min_file_size=2**20, # 文件最小尺寸
)
@my_cache.memoize(typed=True)
def data_process(a=1):
# 加载,处理文件数据,生产数据data, 假设生产的数据为[1, 2, 3]
data = [1, 2, 3]
time.sleep(3)
return data
if __name__ =='__main__':
t1 = time.time()
data_process(a=2)
delt_t = time.time() - t1
print("第一次运行使用时间: ", delt_t, '\n')
t1 = time.time()
data_process(a=2)
delt_t = time.time() - t1
print("第二次运行使用时间: ", delt_t, '\n')
运行结果如下。对比可知,缓存之后,函数体代码并未执行,返回的是磁盘缓存的数据。
第一次运行使用时间: 3.0158493518829346
第二次运行使用时间: 0.0
保存的缓存文件如下,可见数据被缓存成了64个文件夹保存: