如何使用 klepto 在磁盘上使用 LRU 缓存?
How to use LRU caching on disk with klepto?
我正在尝试使用 klepto 进行 LRU 缓存。我想将缓存存储到磁盘,目前正在为此使用 klepto 的 dir_archive
选项。我编写了以下代码,主要基于 klepto 测试脚本中的代码:
def mymap(data):
return hashlib.sha256(data).hexdigest()
class MyLRUCache:
@lru_cache(cache=dir_archive(cached=False), keymap=mymap, ignore='self', maxsize=5)
def __call__(self, data)
return data
call = __call__
def store(self, data):
self.call(data)
# I would also appreciate a better way to do this, if possible.
def lookup(self, key):
return self.call.__cache__()[key]
在缓存达到 maxsize
之前,此代码似乎可以正常工作。那时,lru_cache
不是使用 LRU 删除单个项目,而是清除整个缓存!下面是执行此操作的一段 klepto 源代码 (https://github.com/uqfoundation/klepto/blob/master/klepto/safe.py):
# purge cache
if _len(cache) > maxsize:
if cache.archived():
cache.dump()
cache.clear()
queue.clear()
refcount.clear()
else: # purge least recently used cache entry
key = queue_popleft()
refcount[key] -= 1
while refcount[key]:
key = queue_popleft()
refcount[key] -= 1
del cache[key], refcount[key]
所以我的问题是,为什么 klepto 会清除 "archived" 缓存? lru_cache
和 dir_archive
可以一起使用吗?
此外,如果我的代码看起来完全疯狂,我将非常感谢一些示例代码,说明我应该如何编写此代码,因为 klepto 的文档不多。
补充说明:
我还尝试用 cached=True
定义 dir_archive
。当达到 maxsize
时,内存中的缓存仍会被清除,但缓存的内容会在此时转储到存档缓存中。我对此有几个问题:
- 内存缓存仅在达到
maxsize
之前是准确的,此时它被擦除。
- 归档缓存不受
maxsize
影响。每次内存缓存到达 maxsize
时,内存缓存中的所有项目都会转储到存档缓存中,无论已经存在多少。
- 根据第 1 点和第 2 点,LRU 缓存似乎是不可能的。
答案是你之前不能,但现在你可以。
如果您从 github 获取最新的 klepto
,并提供新标志
purge=False
-- 然后你就会得到你正在寻找的行为。我刚刚添加了这个来回答你的问题。
你的情况:
lru_cache(cache=dir_archive(cached=False), keymap=mymap, ignore='self', maxsize=5, purge=False)
或者,例如:
@lru_cache(maxsize=3, cache=dict_archive('test'), purge=True)
def identity(x):
return x
identity(1)
identity(2)
identity(3)
ic = identity.__cache__()
assert len(ic.keys()) == 3
assert len(ic.archive.keys()) == 0
identity(4)
assert len(ic.keys()) == 0
assert len(ic.archive.keys()) == 4
identity(5)
assert len(ic.keys()) == 1
assert len(ic.archive.keys()) == 4
@lru_cache(maxsize=3, cache=dict_archive('test'), purge=False)
def inverse(x):
return -x
inverse(1)
inverse(2)
inverse(3)
ic = inverse.__cache__()
assert len(ic.keys()) == 3
assert len(ic.archive.keys()) == 0
inverse(4)
assert len(ic.keys()) == 3
assert len(ic.archive.keys()) == 1
inverse(5)
assert len(ic.keys()) == 3
assert len(ic.archive.keys()) == 2
如果这没有达到您的预期,请添加票证。谢谢建议。
我正在尝试使用 klepto 进行 LRU 缓存。我想将缓存存储到磁盘,目前正在为此使用 klepto 的 dir_archive
选项。我编写了以下代码,主要基于 klepto 测试脚本中的代码:
def mymap(data):
return hashlib.sha256(data).hexdigest()
class MyLRUCache:
@lru_cache(cache=dir_archive(cached=False), keymap=mymap, ignore='self', maxsize=5)
def __call__(self, data)
return data
call = __call__
def store(self, data):
self.call(data)
# I would also appreciate a better way to do this, if possible.
def lookup(self, key):
return self.call.__cache__()[key]
在缓存达到 maxsize
之前,此代码似乎可以正常工作。那时,lru_cache
不是使用 LRU 删除单个项目,而是清除整个缓存!下面是执行此操作的一段 klepto 源代码 (https://github.com/uqfoundation/klepto/blob/master/klepto/safe.py):
# purge cache
if _len(cache) > maxsize:
if cache.archived():
cache.dump()
cache.clear()
queue.clear()
refcount.clear()
else: # purge least recently used cache entry
key = queue_popleft()
refcount[key] -= 1
while refcount[key]:
key = queue_popleft()
refcount[key] -= 1
del cache[key], refcount[key]
所以我的问题是,为什么 klepto 会清除 "archived" 缓存? lru_cache
和 dir_archive
可以一起使用吗?
此外,如果我的代码看起来完全疯狂,我将非常感谢一些示例代码,说明我应该如何编写此代码,因为 klepto 的文档不多。
补充说明:
我还尝试用 cached=True
定义 dir_archive
。当达到 maxsize
时,内存中的缓存仍会被清除,但缓存的内容会在此时转储到存档缓存中。我对此有几个问题:
- 内存缓存仅在达到
maxsize
之前是准确的,此时它被擦除。 - 归档缓存不受
maxsize
影响。每次内存缓存到达maxsize
时,内存缓存中的所有项目都会转储到存档缓存中,无论已经存在多少。 - 根据第 1 点和第 2 点,LRU 缓存似乎是不可能的。
答案是你之前不能,但现在你可以。
如果您从 github 获取最新的 klepto
,并提供新标志
purge=False
-- 然后你就会得到你正在寻找的行为。我刚刚添加了这个来回答你的问题。
你的情况:
lru_cache(cache=dir_archive(cached=False), keymap=mymap, ignore='self', maxsize=5, purge=False)
或者,例如:
@lru_cache(maxsize=3, cache=dict_archive('test'), purge=True)
def identity(x):
return x
identity(1)
identity(2)
identity(3)
ic = identity.__cache__()
assert len(ic.keys()) == 3
assert len(ic.archive.keys()) == 0
identity(4)
assert len(ic.keys()) == 0
assert len(ic.archive.keys()) == 4
identity(5)
assert len(ic.keys()) == 1
assert len(ic.archive.keys()) == 4
@lru_cache(maxsize=3, cache=dict_archive('test'), purge=False)
def inverse(x):
return -x
inverse(1)
inverse(2)
inverse(3)
ic = inverse.__cache__()
assert len(ic.keys()) == 3
assert len(ic.archive.keys()) == 0
inverse(4)
assert len(ic.keys()) == 3
assert len(ic.archive.keys()) == 1
inverse(5)
assert len(ic.keys()) == 3
assert len(ic.archive.keys()) == 2
如果这没有达到您的预期,请添加票证。谢谢建议。