Python lru_cache中currsize<misses<maxsize的情况是什么原因导致的?
出现currsize同时小于misses和maxsize的情况,常见有以下几个原因:
调用过
cache_clear()清空缓存lru_cache的hits、misses是累计统计值,从装饰器初始化完成后就会一直累加,不会被重置。而cache_clear()方法只会清空所有缓存条目,将currsize归零,不会修改已经统计的命中、未命中计数。
举个例子:你先调用方法产生2000次未命中,此时currsize为2000,misses为2000;调用cache_clear()后currsize变为0,misses还是2000;后续再产生2312次未命中,最终总misses为4312,currsize为2312,和你给出的运行结果完全吻合。方法执行过程中抛出异常
lru_cache默认不会缓存执行抛出异常的调用结果。如果某次未命中后,方法执行时抛出了异常,这次调用会被计入misses统计,但不会生成对应的缓存条目,currsize不会增加。如果你的文本处理逻辑存在概率性抛出异常的情况(比如输入格式错误、编码异常等),就会出现misses多于currsize的现象。高并发场景下的重复未命中
多线程场景下,如果多个相同参数的请求同时到达,且此时缓存中没有对应条目,这些请求都会被计入misses,但最终只有第一个执行完成的请求结果会被存入缓存,其他请求不会重复写入,也会导致misses略高于currsize,不过这种场景的差值一般不会太大。
你把lru_cache装饰在实例方法上的使用方式存在内存泄漏风险:方法的第一个参数self会被作为缓存键的一部分,持有实例的强引用,会导致实例无法被垃圾回收,除非缓存条目被淘汰或者你手动调用cache_clear()清空缓存。如果业务允许,建议把缓存装饰在无状态的函数上,或者使用functools.cached_property(如果适用)、或者基于实例自己实现缓存逻辑。
内容的提问来源于stack exchange,提问作者Carsten

