Python:构建LRU缓存

时间:2010-12-14 20:32:29

标签: python mongodb lru

我的格式为6,00,000 entries in MongoDB,格式如下:

feature:category:count

其中

  • 功能可以是任何字词,
  • 类别为正面或负面,
  • count 表示该类别的文档中出现的功能的次数。

我想缓存前1000个元组,让我们这样说,不要每次都查询数据库。

如何在Python中构建LRU缓存?或者有任何已知的解决方案吗?

4 个答案:

答案 0 :(得分:17)

Python3.3中的LRU cache具有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 :(得分:5)

除了Python 3.2中包含的版本外,Python核心开发人员Raymond Hettinger还在Python Cookbook中包含了these的LRU缓存配方。

答案 2 :(得分:3)

Python 3.2 functools包含LRU cache。您可以轻松地从repo中挑选它,检查是否必须调整它以使用Python 2(不应该太难 - 可能使用itertools而不是某些内置函数 - 询问您是否需要帮助)并完成。您需要将查询包装成可调用的,并确保它依赖于(hashable)函数参数。

答案 3 :(得分:1)

还有python 3.3版本的lru_cache的后向端口,例如this,它运行在python 2.7上。如果您对两层缓存感兴趣(如果未在实例中缓存它将检查共享缓存)我已根据lru_cache的backport创建了lru2cache