【问题标题】:Python lru_cache: how can currsize < misses < maxsize?Python lru_cache:currsize < misses < maxsize 怎么办?
【发布时间】:2021-10-27 06:52:17
【问题描述】:

我有一个带有 lru_cache annotation 注释的方法的类:

CACHE_SIZE=16384

class MyClass:
    [...]

    @lru_cache(maxsize=CACHE_SIZE)
    def _my_method(self, texts: Tuple[str]):
       <some heavy text processing>

    def cache_info(self):
        return self._my_method.cache_info()

运行一段时间后,通过cache_info()方法查看缓存统计:

c = MyClass()
[...]
c.cache_info()

{
  "hits":9348,
  "misses":4312,
  "maxsize":16384,
  "currsize":2588
}

我的问题是:currsize 怎么可能小于 misses 并且小于 maxsize

我的理解:对于每次未命中,结果都会添加到缓存中,从而增加当前大小。只有当当前大小达到最大大小时,才会删除缓存的结果。由于此处尚未达到最大大小,因此应缓存每个未命中,因此此时currsize 应等于misses。 但是,这似乎不是这种方式。

【问题讨论】:

    标签: python caching lru


    【解决方案1】:

    如果您的程序是多线程的或递归的 - 基本上,在另一个调用部分完成时可能再次调用 _my_method() 的任何类型的条件 - 那么就有可能看到您正在经历的行为。

    lru_cache() 是线程感知的,并使用以下一组步骤进行大小限制缓存:

    • 从包装函数的参数中创建一个哈希键
    • 将缓存锁定在with 块中:
      • 在缓存中查找键
      • 如果key在缓存中,返回缓存值
      • 否则,如果key不在缓存中,则将misses增加1
    • 调用包装函数
    • 再次锁定缓存
      • 如果结果现在在缓存中,则返回它
      • 如果结果仍然不在缓存中,请添加它,可能会删除旧条目等。

    换句话说,缓存的值可能在调用包装函数时已被另一个线程添加,但仍被视为未命中。如果您多次调用_my_method() 查找相同的缺失键,导致misses 递增但随后导致在_my_method() 完成时键出现在缓存中,misses 将高于@ 987654329@.

    【讨论】:

    • 这个解释听起来很可能,谢谢!该类确实在使用多个线程的服务中运行,因此对缓存的请求可以并行进行。
    猜你喜欢
    • 2021-02-05
    • 1970-01-01
    • 2012-03-18
    • 1970-01-01
    • 1970-01-01
    • 2010-11-04
    • 1970-01-01
    • 2011-03-19
    • 2019-11-18
    相关资源
    最近更新 更多