Кэширование LRU с учетом памяти в Python?

Я использую встроенный в Python 3 декоратор functools.lru_cache, чтобы запомнить некоторые дорогостоящие функции. Я хотел бы запомнить как можно больше вызовов, не используя слишком много памяти, поскольку кеширование слишком большого количества значений вызывает перегрузку.

Есть ли предпочтительный метод или библиотека для выполнения этого в Python?

Например, этот вопрос привел меня к библиотеке Go для кэширование LRU с учетом системной памяти. Что-то подобное для Python было бы идеально.


Примечание: я не могу просто оценить объем памяти, используемый для каждого значения, и соответствующим образом установить maxsize, так как несколько процессов будут вызывать декорированную функцию параллельно; решение должно фактически динамически проверять, сколько памяти свободно.


person Will    schedule 05.05.2014    source источник
comment
Если вы не можете найти что-то, что уже делает это, вы можете попробовать использовать psutil (code.google. .com/p/psutil), чтобы создать свой собственный.   -  person dano    schedule 05.05.2014
comment
Да, это то, что я сейчас изучаю — на самом деле, вы случайно не знаете, как найти исходный код для реализации Python 3 lru_cache? Самый простой способ — просто проверить использование памяти в декораторе. Это наверняка добавит некоторые накладные расходы, но я не думаю, что в этом приложении это будет существенно.   -  person Will    schedule 05.05.2014
comment
@Will для источника см. functools.py:370 и парой строк выше для функций клавиш кеша.   -  person Lukas Graf    schedule 05.05.2014
comment
Или локально: Запустите интерактивный интерпретатор Python import functools и просто введите имя модуля functools. Работает для любого поиска источника практически любого модуля Python (конечно, кроме расширений C).   -  person Lukas Graf    schedule 05.05.2014
comment
@LukasGraf, о да, конечно! -____- Спасибо!   -  person Will    schedule 05.05.2014
comment
@Will Кстати, functools.lru_cache написал Рэймонд Хеттингер. Он опубликовал несколько различных (LRU) рецептов кэширования/мемоизации, возможно, в них можно найти что-то полезное или хотя бы вдохновляющее ;-)   -  person Lukas Graf    schedule 05.05.2014
comment
@LukasGraf, приятно знать :)   -  person Will    schedule 05.05.2014
comment
Спасибо, ребята, кажется, работает хорошо. Разместил код в моем ответе. Дайте мне знать, если это вообще можно улучшить!   -  person Will    schedule 06.05.2014
comment
Я спросил в github.com/tkem/cachetools/issues/152 Мы увидим: )   -  person Mišo    schedule 06.12.2019


Ответы (1)


В итоге я изменил встроенный lru_cache, чтобы использовать psutil.

Модифицированный декоратор принимает дополнительный необязательный аргумент use_memory_up_to. Если установлено, кэш будет считаться заполненным, если доступно менее use_memory_up_to байт памяти (согласно psutil.virtual_memory().available). Например:

from .lru_cache import lru_cache

GB = 1024**3

@lru_cache(use_memory_up_to=(1 * GB))
def expensive_func(args):
    ...

Примечание. установка use_memory_up_to приведет к тому, что maxsize не будет иметь никакого эффекта.

Вот код: lru_cache.py

person Will    schedule 05.05.2014