Как использовать кэширование LRU на диске с клепто?
Я пытаюсь использовать клепто для LRU-кэширования. Я хотел бы сохранить кэш на диск, и в настоящее время я использую Klepto's 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 для удаления одного элемента, lru_cache
удаляет весь кеш! Ниже приведен фрагмент исходного кода 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 удаляет "заархивированные" кэши? Можно ли использовать lru_cache
а также dir_archive
все вместе?
Кроме того, если мой код выглядит совершенно чокнутым, я был бы очень признателен за некоторый пример кода того, как я должен писать это, так как для klepto не было много документации.
ДОПОЛНИТЕЛЬНЫЕ ЗАМЕЧАНИЯ: я также попытался определить dir_archive
с cached=True
, Кэш в памяти все еще очищается, когда maxsize
достигнут, но содержимое кеша сбрасывается в заархивированный кеш в этот момент. У меня есть несколько проблем с этим:
- Кэш в памяти точен только до
maxsize
достигается, в этот момент он стирается. - На архивированный кеш не влияет
maxsize
, Каждый разmaxsize
достигается кэшем в памяти, все элементы в кэше в памяти выгружаются в архивный кеш, независимо от того, сколько их уже есть. - Кэширование LRU кажется невозможным на основании пунктов 1 и 2.
1 ответ
Ответ в том, что вы не могли раньше ответить на свой вопрос, но теперь вы можете. Если вы получаете самые последние klepto
от GitHub, и предоставьте новый флаг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
Пожалуйста, добавьте билет, если это не делает то, что вы ожидали. Спасибо за предложение.