02_LRU_cache

2019-07-15  本文已影响0人  蕴重Liu
"""
python3 only
LRU cache
"""
from collections import OrderedDict
from functools import wraps

"""缓存装饰器"""
def cache(func):
    """先引入一个简单的装饰器缓存,其实原理很简单,就是内部用一个字典缓存已经计算过的结果"""
    store = {}

    @wraps(func)
    def _(n): # 函数命名没实际意义,随便命名
        if n in store:
            return store[n]
        else:
            res = func(n)
            store[n] = res
            return res
    return _

@cache
def f(n):
    if n <= 1:
        return n
    return f(n - 1) + f(n - 2)


class LRUCache:
    def __init__(self, capacity=128):
        self.capacity = capacity
        # OrderedDict 内部也是用循环双端链表实现
        self.od = OrderedDict

    def get(self, key, default=None):
        val = self.od.get(key, default)
        self.od.move_to_end(key) #最近被访问的放到最后面
        return val

    def add_or_update(self, key, value):
        if key in self.od:
            self.od[key] = value
            self.od.move_to_end(key)
        else:
            self.od[key] = value
            if len(self.od) > self.capacity:
                self.od.popitem(last=False)

    def __call__(self, func):
        """
        简单的LRU实现策略
        1 使用内置的dict,实际上是存储到python进程里,而使用redis可存储更多数据到服务器
        2 同时考虑超时timeout参数,如menmcahce的lazy expiration策略
        3 缺点:对于周期性的数据访问会导致命中率迅速下降,有一种优化是LRU-K,访问次数达到k次才将数据放入缓存
        """
        def _(n):
            if n in self.od:
                return self.get(n)
            else:
                val = func(n)
                self.add_or_update(n, val)
                return val
        return _

@LRUCache(10)
def f_use_lru(n):
    if n <= 1:
        return n
    return f(n-1) + f(n-2)

def test():
    import time
    beg = time.time()
    for i in range(34):
        print(f(i))
    print(time.time() - beg)
    beg = time.time()
    for i in range(34):
        print(f_use_lru(i))
    print(time.time() - beg)

if __name__ == '__main__':
    test()
0
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181
6765
10946
17711
28657
46368
75025
121393
196418
317811
514229
832040
1346269
2178309
3524578
0.0
上一篇 下一篇

猜你喜欢

热点阅读