2010-12-14 3 views
7

У меня есть около 6,00,000 entries in MongoDB в следующем формате:Python: построение кэша LRU

feature:category:count 

где

  • функция может быть любое слово,
  • категории является положительным или отрицательным , и
  • кол-во показывает, сколько раз в документе для этой категории произошла функция.

Я хочу кэшировать первые 1000 кортежей, допустим, чтобы не запрашивать базу данных каждый раз.

Как построить кеш LRU в Python? Или есть какие-то известные решения?

ответ

3

Python 3.2 functools содержит LRU cache. Вы можете легко черри его от repo, проверьте, нужно ли настраивать его для работы с Python 2 (не должно быть слишком сложно - возможно, используя itertools вместо определенных встроенных функций - спросите, нужна ли вам помощь) и сделайте. Вам нужно обернуть запрос в вызываемый и убедиться, что он зависит от аргументов функции (hashable).

+0

Это кажется интересным, но как получить его из репо ??? Я не знаю, как это сделать \ – daydreamer

+0

@learner: Самый простой способ - копировать его из файла, с которым я связан. – delnan

+0

Я пытался, но когда я пытаюсь импортировать functools он выдает ошибку >>> импорт functools Traceback (самый последний вызов последнего): Файл «», строка 1, в Файл «functools.py», строка 151 нелокального хитов, пропусков ^ Синтаксис: недействительный синтаксис Ошибка в sys.excepthook: – daydreamer

5

Помимо версии, включенной в Python 3.2, существуют рецепты кэша LRU в Python Cookbook, включая these разработчика ядра Python Раймонда Хеттингера.

17

LRU cache в Python3.3 имеет O (1) вставку, удаление и поиск.

В проекте используется круговой дважды связанный список записей (расположенных от самых старых до новейших) и хеш-таблицы для определения отдельных ссылок. Кэш-хиты используют хеш-таблицу, чтобы найти соответствующую ссылку и переместить ее в начало списка. Кэш пропускает удаление самой старой ссылки и создает новую ссылку во главе связанного списка.

Вот упрощенная (но быстрая) версия в 33 строках очень простого Python (с использованием только простых операций с словарем и списками). Он работает на Python2.0 и позже (или PyPy или Jython или Python3.x):

class LRU_Cache: 

    def __init__(self, original_function, maxsize=1024): 
     # Link structure: [PREV, NEXT, KEY, VALUE] 
     self.root = [None, None, None, None] 
     self.root[0] = self.root[1] = self.root 
     self.original_function = original_function 
     self.maxsize = maxsize 
     self.mapping = {} 

    def __call__(self, *key): 
     mapping = self.mapping 
     root = self.root 
     link = mapping.get(key) 
     if link is not None: 
      link_prev, link_next, link_key, value = link 
      link_prev[1] = link_next 
      link_next[0] = link_prev 
      last = root[0] 
      last[1] = root[0] = link 
      link[0] = last 
      link[1] = root 
      return value 
     value = self.original_function(*key) 
     if len(mapping) >= self.maxsize: 
      oldest = root[1] 
      next_oldest = oldest[1] 
      root[1] = next_oldest 
      next_oldest[0] = root 
      del mapping[oldest[2]] 
     last = root[0] 
     last[1] = root[0] = mapping[key] = [last, root, key, value] 
     return value 


if __name__ == '__main__': 
    p = LRU_Cache(ord, maxsize=3) 
    for c in 'abcdecaeaa': 
     print(c, p(c)) 
1

Там также Бэкпорт версии питона 3.3 lru_cache, таких как this, который работает на Python 2.7. Если вас интересуют два уровня кеширования (если они не кэшированы в экземпляре, он будет проверять общий кеш), я создал lru2cache на основе обратного пути lru_cache.

Смежные вопросы