Python lru_cache: currsize < misses < maxsize 怎么办?
Python lru_cache: how can currsize < misses < maxsize?
我有一个 class 方法,该方法用 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
。
但是,这似乎不是它的工作方式。
如果您的程序是多线程的或递归的 - 基本上,任何类型的条件 _my_method()
可能会在另一个调用部分完成时再次调用 - 那么有可能看到你的行为正在经历。
lru_cache()
是线程感知的,并使用以下一组步骤进行大小限制缓存:
- 从包装函数的参数中创建哈希键
- 将缓存锁定在
with
块中:
- 在缓存中查找key
- 如果键在缓存中,return缓存值
- 否则,如果密钥不在缓存中,则将
misses
增加 1
- 调用包装函数
- 再次锁定缓存
- 如果结果现在在缓存中,return它
- 如果结果仍然不在缓存中,请添加它,可能会删除较旧的条目等。
换句话说,缓存的值可能已在调用包装函数时由另一个线程添加,但仍算作未命中。如果您多次调用 _my_method()
查找相同的缺失键,导致 misses
递增,但随后导致键在 _my_method()
完成时出现在缓存中,misses
将高于 currsize
.
我有一个 class 方法,该方法用 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
。
但是,这似乎不是它的工作方式。
如果您的程序是多线程的或递归的 - 基本上,任何类型的条件 _my_method()
可能会在另一个调用部分完成时再次调用 - 那么有可能看到你的行为正在经历。
lru_cache()
是线程感知的,并使用以下一组步骤进行大小限制缓存:
- 从包装函数的参数中创建哈希键
- 将缓存锁定在
with
块中:- 在缓存中查找key
- 如果键在缓存中,return缓存值
- 否则,如果密钥不在缓存中,则将
misses
增加 1
- 调用包装函数
- 再次锁定缓存
- 如果结果现在在缓存中,return它
- 如果结果仍然不在缓存中,请添加它,可能会删除较旧的条目等。
换句话说,缓存的值可能已在调用包装函数时由另一个线程添加,但仍算作未命中。如果您多次调用 _my_method()
查找相同的缺失键,导致 misses
递增,但随后导致键在 _my_method()
完成时出现在缓存中,misses
将高于 currsize
.