分享python实现的lfu缓存模块-pylfu

根据老外的一篇文章改成的lfu模块,我发现在github或者是pypi里面是有大量的lru代码,但是lfu的反而没有,看来和我一样都喜欢用fifo和lru的算法。。。 那我自己麻烦点,放到开源的库里面, 供应大家下载。  老外的原文连接是在 http://code.activestate.com/recipes/498245-lru-and-lfu-cache-decorators/    。 这里额外的提醒下大家,他的性能还是可以的,如果做缓存的数据很大,那么我强烈推荐大家用redis做lfu的数据源,而不是自己用python把lru和lfu做封装。  我自己吃过亏的,在超过10G的内存使用量下,发现lfu和lru对于计数速度有些慢了。有时候还会被系统给OOM掉,如果放在redis里,还可以做一定的持久化。 

文章的原文在  http://xiaorui.cc

你可以直接用pip安装pylfu

pip install pylfu

也可以自己git clone下来,然后进行修改。 

https://github.com/rfyiamcool/pylfu

下面是python 实现lfu的代码

import collections
import functools
from itertools import ifilterfalse
from heapq import nsmallest
from operator import itemgetter
class Counter(dict):
    def __missing__(self, key):
        return 0
def lfu_cache(maxsize=100):

    def decorating_function(user_function):
        cache = {}                      # mapping of args to results
        use_count = Counter()           # times each key has been accessed
        kwd_mark = object()             # separate positional and keyword args

        @functools.wraps(user_function)
        def wrapper(*args, **kwds):
            key = args
            if kwds:
                key += (kwd_mark,) + tuple(sorted(kwds.items()))
            use_count[key] += 1

            # get cache entry or compute if not found
            try:
                result = cache[key]
                wrapper.hits += 1
            except KeyError:
                result = user_function(*args, **kwds)
                cache[key] = result
                wrapper.misses += 1

                # purge least frequently used cache entry
                if len(cache) > maxsize:
                    for key, _ in nsmallest(maxsize // 10,
                                            use_count.iteritems(),
                                            key=itemgetter(1)):
                        del cache[key], use_count[key]

            return result

        def clear():
            cache.clear()
            use_count.clear()
            wrapper.hits = wrapper.misses = 0

        wrapper.hits = wrapper.misses = 0
        wrapper.clear = clear
        return wrapper
    return decorating_function


if __name__ == '__main__':


    @lfu_cache(maxsize=20)
    def f(x, y):
        return 3*x+y

    domain = range(5)
    from random import choice
    for i in range(1000):
        r = f(choice(domain), choice(domain))

    print(f.hits, f.misses)


大家觉得文章对你有些作用! 如果想赏钱,可以用微信扫描下面的二维码,感谢!
另外再次标注博客原地址  xiaorui.cc

5 Responses

  1. Ficapy 2015年4月27日 / 下午6:35

    你这个反爬虫太厉害,图片正常情况下载我这里也没法看

  2. 专业dba 2015年4月27日 / 上午7:35

    LFU用处很小

    • 峰云就她了 2015年4月27日 / 上午10:36

      看场景,我们常见的场景都是是用LRU的

  3. 人品好 2015年4月21日 / 上午11:16

    最近忙啥?

发表评论

邮箱地址不会被公开。 必填项已用*标注