Python中functools与joblib的@cache装饰器差异及性能疑问
functools.cache 与 joblib.cache 的核心区别
1. 存储介质与适用场景
functools.cache:纯内存缓存,专为小体积、可哈希的Python对象设计(比如数值、字符串、小型元组)。仅适配纯函数(输入固定则输出固定,无副作用),程序退出后缓存完全清空。joblib.cache:支持内存/磁盘双存储,主打大对象缓存(比如大型numpy数组、训练好的机器学习模型)。磁盘缓存可跨Python会话持久化,甚至能在多进程间共享,适合重复计算成本极高的场景。
2. 缓存机制与灵活性
functools.cache:本质是lru_cache(maxsize=None),无淘汰策略——只要内存足够,缓存的结果会一直保留,仅用普通字典实现键值对查找。joblib.cache:默认带LRU淘汰策略,还支持缓存压缩、过期清理、自定义序列化器等高级配置,对缓存的生命周期和存储方式控制更灵活。
3. 性能与限制
functools.cache:无序列化/磁盘IO开销,纯内存字典操作速度极快,但要求函数参数必须是可哈希类型(比如列表不能直接用,需转元组)。joblib.cache:磁盘存储时会有IO和序列化开销,但对大对象而言,重复计算的成本远高于这些开销,反而能大幅节省时间。它支持更多非哈希但可序列化的参数类型。
为什么无限制缓存的
functools.cache比带大小限制的lru_cache更快更小? 这是个逻辑误区:不是“存储更多值”导致更快更小,而是因为它不需要LRU淘汰逻辑,才允许无限制存储,同时性能更优。
具体原因:
- 去掉了LRU的维护开销:带
maxsize限制的lru_cache需要维护一个双向链表来记录缓存条目的访问顺序,每次命中或写入缓存时都要更新链表位置,用来在缓存满时淘汰最久未使用的条目。这部分额外操作会增加时间成本。而functools.cache(即maxsize=None)完全跳过了这个逻辑,只用普通字典做O(1)的键值查找和插入,没有额外维护工作。 - 减少了元数据占用:LRU实现需要为每个缓存条目存储额外的链表节点、访问时间戳等元数据,而纯字典缓存只存参数(键)和结果(值),相同数量的缓存条目下,内存占用更小。
- 无限制存储是结果而非原因:因为不需要淘汰逻辑,所以它可以无限制存储缓存结果,但这是“没有LRU开销”带来的附加特性,而非性能提升的原因。如果你的函数调用参数范围不大,这种无限制缓存能最大化复用结果;但如果参数范围极广,内存会持续增长,这时候才需要带
maxsize的lru_cache来控制内存占用。
内容的提问来源于stack exchange,提问作者alexis_thual
相关产品推荐
相关产品推荐

