1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 from collections import deque
22 from weakref import WeakValueDictionary
23 import gc
24
25
27 """Caching dictionary like object that discards the least recently
28 used objects when number of cached items exceeds maxsize.
29
30 cullsize is the fraction of items that will be discarded when
31 maxsize is reached.
32 """
33
34 - def __init__(self, maxsize, cullsize=2, peakmult=10, aggressive_gc=True, *args, **kwargs):
35 self.cullsize = max(2, cullsize)
36 self.maxsize = max(cullsize, maxsize)
37 self.aggressive_gc = aggressive_gc
38 self.peakmult = peakmult
39 self.queue = deque()
40 WeakValueDictionary.__init__(self, *args, **kwargs)
41
43 """free memory by deleting old items from cache"""
44
45
46
47
48
49
50
51
52 while len(self) >= self.maxsize <= len(self.queue):
53 cullsize = max(int(len(self.queue) / self.cullsize), 2)
54 try:
55 for i in xrange(cullsize):
56 self.queue.popleft()
57 except IndexError:
58
59
60 break
61
62
63
64
65 if self.aggressive_gc:
66 rounds = min(max(int(self.aggressive_gc), 5), 50)
67 for i in xrange(rounds):
68 gc.collect()
69 else:
70 gc.collect()
71
73
74 while len(self.queue) and self.queue[0][0] == key:
75
76
77 self.queue.popleft()
78
79 while len(self.queue) and self.queue[-1][0] == key:
80
81
82 self.queue.pop()
83
84 if len(self) >= self.maxsize or len(self.queue) >= self.maxsize * self.peakmult:
85 self.cull()
86
87 self.queue.append((key, value))
88 WeakValueDictionary.__setitem__(self, key, value)
89
91 value = WeakValueDictionary.__getitem__(self, key)
92
93 while len(self.queue) > 0 and self.queue[0][0] == key:
94
95
96 self.queue.popleft()
97
98
99 if not (len(self.queue) and self.queue[-1][0] == key):
100 if len(self) >= self.maxsize or len(self.queue) >= self.maxsize * self.peakmult:
101 self.cull()
102 self.queue.append((key, value))
103
104 return value
105
107
108
109 while len(self.queue) and self.queue[0][0] == key:
110
111
112 self.queue.popleft()
113
114 while len(self.queue) and self.queue[-1][0] == key:
115
116
117 self.queue.pop()
118
119 return WeakValueDictionary.__delitem__(self, key)
120
122 self.queue.clear()
123 return WeakValueDictionary.clear(self)
124
126 if key not in self:
127 self[key] = default
128
129 return self[key]
130