在阅读有关Python re
模块的文档时,我决定查看re.py
源代码。
当我打开它时,我发现了这个:
_cache = {}
_MAXCACHE = 100
def _compile(*key):
cachekey = (type(key[0]),) + key
p = _cache.get(cachekey)
if p is not None:
return p
#...Here I skip some part of irrelevant to the question code...
if len(_cache) >= _MAXCACHE:
_cache.clear()
_cache[cachekey] = p
return p
为什么在达到_cache.clear()
条目时使用_MAXCACHE
清除缓存?
完全清除缓存并从头开始是否常见?
为什么不使用最久前的兑现值被删除?
答案 0 :(得分:5)
以下是计划针对缓存的新regex
模块的开发人员之一的引用,这是将新模块与当前re
模块分开的功能列表的一部分
7)修改重新编译的表达式缓存以更好地处理 捶打情况。目前,在编译正则表达式时 结果是缓存的,如果再次编译相同的表达式, 它是从缓存中检索的,不需要做额外的工作。这个 缓存最多支持100个条目。一旦达到第100个条目, 清除缓存并且必须进行新的编译。危险,一切都是这样 很少见,是可以编译第100个表达式只找到那个 重新编译它,并且必须重新做同样的工作 已经完成了3个表达式之前。通过稍微修改这个逻辑,它 可以建立一个给出时间戳的任意计数器 每个编译的条目,而不是清除整个缓存时 达到容量,只消除最旧的一半缓存,保持 最近的一半。这应该限制了可能性 抨击大量正则表达式的情况 不断重新编译。除此之外,我还会更新限制 256个条目,意味着最近保留了128个条目。
http://bugs.python.org/issue2636
这似乎表明开发人员的懒惰或“强调可读性”更有可能解释当前的缓存行为。
答案 1 :(得分:3)
如果我不得不猜测我会说这样做是为了避免跟踪个别值何时/多长时间存储在缓存中,这会产生内存和处理开销。因为正在使用的缓存对象是一个本质上无序的字典,所以没有好的方法可以知道在没有其他缓存对象的情况下添加了哪些订单项。这可以通过使用OrderedDict代替标准字典来解决,假设您正在使用Python> = 2.7,否则,您需要重新设计缓存的实现方式,以消除对clear()
。
答案 2 :(得分:1)
缓存的目的是减少函数的平均调用时间。与在_cache
中保留更多信息并修剪而不是清除它相关的开销会增加平均呼叫时间。 _cache.clear()
调用将很快完成,即使您丢失了缓存,这也优于维护缓存状态,并且在达到限制时会有从缓存中删除单个元素的开销。
计算缓存效率时需要考虑以下几点:
问题是增加#3是否有意义,如果它意味着增加#2和#4。我的猜测是,它没有,或者差别可以忽略不计,保持代码简单是可取的。