gpt4 book ai didi

python - 将 WeakValueDictionary 用于缓存时的 GC 问题

转载 作者:太空狗 更新时间:2023-10-30 01:16:54 25 4
gpt4 key购买 nike

根据 weakref 模块的官方 Python 文档,“弱引用的主要用途是实现包含大对象的缓存或映射,...”。因此,我使用 Wea​​kValueDictionary 为长时间运行的函数实现缓存机制。然而,事实证明,缓存中的值在实际再次使用之前永远不会保留在那里,而是几乎每次都需要重新计算。由于对存储在 WeakValueDictionary 中的值的访问之间没有强引用,因此 GC 摆脱了它们(即使内存绝对没有问题)。

现在,我应该如何使用弱引用来实现缓存?如果我在某处明确保留强引用以防止 GC 删除我的弱引用,那么一开始就没有必要使用 Wea​​kValueDictionary。 GC 可能应该有一些选项告诉它:仅当内存用完(或超过某个阈值)时,删除所有没有引用的所有内容和所有具有弱引用的内容。有类似的东西吗?或者对于这种缓存有更好的策略吗?

最佳答案

我将尝试通过如何使用 weakref 模块实现缓存的示例来回答您的询问。我们会将缓存的弱引用保存在 weakref.WeakValueDictionary 中,将强引用保存在 collections.deque 中,因为它具有 maxlen 属性控制它持有多少对象。以函数闭包方式实现:

import weakref, collections
def createLRUCache(factory, maxlen=64):
weak = weakref.WeakValueDictionary()
strong = collections.deque(maxlen=maxlen)

notFound = object()
def fetch(key):
value = weak.get(key, notFound)
if value is notFound:
weak[key] = value = factory(key)
strong.append(value)
return value
return fetch

deque 对象将只保留最后的 maxlen 条目,一旦达到容量就简单地删除对旧条目的引用。当旧条目被丢弃并被 python 收集为垃圾时,WeakValueDictionary 将从映射中删除这些键。因此,这两个对象的组合帮助我们在 LRU 缓存中仅保留 maxlen 条目。

class Silly(object):
def __init__(self, v):
self.v = v

def fib(i):
if i > 1:
return Silly(_fibCache(i-1).v + _fibCache(i-2).v)
elif i: return Silly(1)
else: return Silly(0)
_fibCache = createLRUCache(fib)

关于python - 将 WeakValueDictionary 用于缓存时的 GC 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9687921/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com