src/eric7/EricUtilities/EricCache.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9653
e67609152c5e
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
11 11
12 12
13 class EricCache: 13 class EricCache:
14 """ 14 """
15 Class implementing a LRU cache of a specific size. 15 Class implementing a LRU cache of a specific size.
16 16
17 If the maximum number of entries is exceeded, the least recently used item 17 If the maximum number of entries is exceeded, the least recently used item
18 is removed from the cache. A cache hit moves the entry to the front of the 18 is removed from the cache. A cache hit moves the entry to the front of the
19 cache. 19 cache.
20 """ 20 """
21
21 def __init__(self, size=100): 22 def __init__(self, size=100):
22 """ 23 """
23 Constructor 24 Constructor
24 25
25 @param size maximum number of entries that may be stored in the cache 26 @param size maximum number of entries that may be stored in the cache
26 @type int 27 @type int
27 @exception ValueError raised to indicate an illegal 'size' parameter 28 @exception ValueError raised to indicate an illegal 'size' parameter
28 """ 29 """
29 if size < 0: 30 if size < 0:
30 raise ValueError("'size' parameter must be positive.") 31 raise ValueError("'size' parameter must be positive.")
31 32
32 self.__size = size 33 self.__size = size
33 34
34 # internal objects 35 # internal objects
35 self.__keyList = [] 36 self.__keyList = []
36 self.__store = {} # stores the cache entries 37 self.__store = {} # stores the cache entries
37 self.__accesStore = {} # stores the last access date and times 38 self.__accesStore = {} # stores the last access date and times
38 self.__hits = 0 39 self.__hits = 0
39 self.__misses = 0 40 self.__misses = 0
40 self.__maxsize = 0 41 self.__maxsize = 0
41 self.__maxCacheTime = 0 # 0 seconds means aging is disabled 42 self.__maxCacheTime = 0 # 0 seconds means aging is disabled
42 43
43 self.__cacheTimer = QTimer() 44 self.__cacheTimer = QTimer()
44 self.__cacheTimer.setSingleShot(True) 45 self.__cacheTimer.setSingleShot(True)
45 self.__cacheTimer.timeout.connect(self.__pruneCache) 46 self.__cacheTimer.timeout.connect(self.__pruneCache)
46 47
47 def __moveLast(self, key): 48 def __moveLast(self, key):
48 """ 49 """
49 Private method to move a cached item to the MRU position. 50 Private method to move a cached item to the MRU position.
50 51
51 @param key key of the item to be retrieved 52 @param key key of the item to be retrieved
52 @type any hashable type that can be used as a dict key 53 @type any hashable type that can be used as a dict key
53 """ 54 """
54 self.__keyList.remove(key) 55 self.__keyList.remove(key)
55 self.__keyList.append(key) 56 self.__keyList.append(key)
56 57
57 def __adjustToSize(self): 58 def __adjustToSize(self):
58 """ 59 """
59 Private method to adjust the cache to its size. 60 Private method to adjust the cache to its size.
60 """ 61 """
61 if self.__size: 62 if self.__size:
62 removeList = self.__keyList[:-self.__size] 63 removeList = self.__keyList[: -self.__size]
63 self.__keyList = self.__keyList[-self.__size:] 64 self.__keyList = self.__keyList[-self.__size :]
64 for key in removeList: 65 for key in removeList:
65 del self.__store[key] 66 del self.__store[key]
66 del self.__accesStore[key] 67 del self.__accesStore[key]
67 else: 68 else:
68 self.reset() 69 self.reset()
69 70
70 def getSize(self): 71 def getSize(self):
71 """ 72 """
72 Public method to get the maximum size of the cache. 73 Public method to get the maximum size of the cache.
73 74
74 @return maximum number of entries of the cache 75 @return maximum number of entries of the cache
75 @rtype int 76 @rtype int
76 """ 77 """
77 return self.__size 78 return self.__size
78 79
79 def setSize(self, newSize): 80 def setSize(self, newSize):
80 """ 81 """
81 Public method to change the maximum size of the cache. 82 Public method to change the maximum size of the cache.
82 83
83 @param newSize maximum number of entries that may be stored in the 84 @param newSize maximum number of entries that may be stored in the
84 cache 85 cache
85 @type int 86 @type int
86 """ 87 """
87 if newSize >= 0: 88 if newSize >= 0:
88 self.__size = newSize 89 self.__size = newSize
89 self.__adjustToSize() 90 self.__adjustToSize()
90 91
91 def getMaximumCacheTime(self): 92 def getMaximumCacheTime(self):
92 """ 93 """
93 Public method to get the maximum time entries may exist in the cache. 94 Public method to get the maximum time entries may exist in the cache.
94 95
95 @return maximum cache time in seconds 96 @return maximum cache time in seconds
96 @rtype int 97 @rtype int
97 """ 98 """
98 return self.__maxCacheTime 99 return self.__maxCacheTime
99 100
100 def setMaximumCacheTime(self, time): 101 def setMaximumCacheTime(self, time):
101 """ 102 """
102 Public method to set the maximum time entries may exist in the cache. 103 Public method to set the maximum time entries may exist in the cache.
103 104
104 @param time maximum cache time in seconds 105 @param time maximum cache time in seconds
105 @type int 106 @type int
106 """ 107 """
107 if time != self.__maxCacheTime: 108 if time != self.__maxCacheTime:
108 self.__cacheTimer.stop() 109 self.__cacheTimer.stop()
109 self.__pruneCache() 110 self.__pruneCache()
110 self.__maxCacheTime = time 111 self.__maxCacheTime = time
111 if self.__maxCacheTime > 0: 112 if self.__maxCacheTime > 0:
112 self.__cacheTimer.setInterval(self.__maxCacheTime * 1000) 113 self.__cacheTimer.setInterval(self.__maxCacheTime * 1000)
113 self.__cacheTimer.start() 114 self.__cacheTimer.start()
114 115
115 def get(self, key): 116 def get(self, key):
116 """ 117 """
117 Public method to get an entry from the cache given its key. 118 Public method to get an entry from the cache given its key.
118 119
119 If the key is present in the cache, it is moved to the MRU position. 120 If the key is present in the cache, it is moved to the MRU position.
120 121
121 @param key key of the item to be retrieved 122 @param key key of the item to be retrieved
122 @type any hashable type that can be used as a dict key 123 @type any hashable type that can be used as a dict key
123 @return cached item for the given key or None, if the key is not 124 @return cached item for the given key or None, if the key is not
124 present 125 present
125 @rtype object or None 126 @rtype object or None
130 self.__accesStore[key] = QDateTime.currentDateTimeUtc() 131 self.__accesStore[key] = QDateTime.currentDateTimeUtc()
131 return self.__store[key] 132 return self.__store[key]
132 else: 133 else:
133 self.__misses += 1 134 self.__misses += 1
134 return None 135 return None
135 136
136 def add(self, key, item): 137 def add(self, key, item):
137 """ 138 """
138 Public method to add an item to the cache. 139 Public method to add an item to the cache.
139 140
140 If the key is already in use, the cached item is replaced by the new 141 If the key is already in use, the cached item is replaced by the new
141 one given and is moved to the MRU position 142 one given and is moved to the MRU position
142 143
143 @param key key of the item to be retrieved 144 @param key key of the item to be retrieved
144 @type any hashable type that can be used as a dict key 145 @type any hashable type that can be used as a dict key
145 @param item item to be cached under the given key 146 @param item item to be cached under the given key
146 @type object 147 @type object
147 """ 148 """
149 self.__moveLast(key) 150 self.__moveLast(key)
150 else: 151 else:
151 self.__keyList.append(key) 152 self.__keyList.append(key)
152 self.__store[key] = item 153 self.__store[key] = item
153 self.__accesStore[key] = QDateTime.currentDateTimeUtc() 154 self.__accesStore[key] = QDateTime.currentDateTimeUtc()
154 155
155 self.__adjustToSize() 156 self.__adjustToSize()
156 157
157 self.__maxsize = max(self.__maxsize, len(self.__keyList)) 158 self.__maxsize = max(self.__maxsize, len(self.__keyList))
158 159
159 def remove(self, key): 160 def remove(self, key):
160 """ 161 """
161 Public method to remove an item from the cache. 162 Public method to remove an item from the cache.
162 163
163 @param key key of the item to be retrieved 164 @param key key of the item to be retrieved
164 @type any hashable type that can be used as a dict key 165 @type any hashable type that can be used as a dict key
165 """ 166 """
166 if key in self.__store: 167 if key in self.__store:
167 del self.__store[key] 168 del self.__store[key]
168 del self.__accesStore[key] 169 del self.__accesStore[key]
169 self.__keyList.remove(key) 170 self.__keyList.remove(key)
170 171
171 def clear(self): 172 def clear(self):
172 """ 173 """
173 Public method to clear the cache. 174 Public method to clear the cache.
174 """ 175 """
175 self.__keyList = [] 176 self.__keyList = []
176 self.__store = {} 177 self.__store = {}
177 self.__accesStore = {} 178 self.__accesStore = {}
178 179
179 def reset(self): 180 def reset(self):
180 """ 181 """
181 Public method to reset the cache. 182 Public method to reset the cache.
182 183
183 This is like clear() but sets the various counters to their initial 184 This is like clear() but sets the various counters to their initial
184 value as well. 185 value as well.
185 """ 186 """
186 self.clear() 187 self.clear()
187 self.__hits = 0 188 self.__hits = 0
188 self.__misses = 0 189 self.__misses = 0
189 self.__maxsize = 0 190 self.__maxsize = 0
190 191
191 def length(self): 192 def length(self):
192 """ 193 """
193 Public method to get the current length of the cache. 194 Public method to get the current length of the cache.
194 195
195 @return current length of the cache 196 @return current length of the cache
196 @rtype int 197 @rtype int
197 """ 198 """
198 return len(self.__keyList) 199 return len(self.__keyList)
199 200
200 def info(self): 201 def info(self):
201 """ 202 """
202 Public method to get some information about the cache. 203 Public method to get some information about the cache.
203 204
204 @return dictionary containing the cache info 205 @return dictionary containing the cache info
205 @rtype dict (with keys "hits", "misses", "maxsize", "currsize") 206 @rtype dict (with keys "hits", "misses", "maxsize", "currsize")
206 """ 207 """
207 return { 208 return {
208 "hits": self.__hits, 209 "hits": self.__hits,
209 "misses": self.__misses, 210 "misses": self.__misses,
210 "maxsize": self.__maxsize, 211 "maxsize": self.__maxsize,
211 "currsize": self.length(), 212 "currsize": self.length(),
212 } 213 }
213 214
214 def __pruneCache(self): 215 def __pruneCache(self):
215 """ 216 """
216 Private slot to prune outdated cache entries and restart the timer. 217 Private slot to prune outdated cache entries and restart the timer.
217 """ 218 """
218 if self.__maxCacheTime > 0: 219 if self.__maxCacheTime > 0:
219 current = QDateTime.currentDateTimeUtc() 220 current = QDateTime.currentDateTimeUtc()
220 221
221 keysToBeDeleted = [] 222 keysToBeDeleted = []
222 for key, lastAccessTime in self.__accesStore.items(): 223 for key, lastAccessTime in self.__accesStore.items():
223 if lastAccessTime.secsTo(current) > self.__maxCacheTime: 224 if lastAccessTime.secsTo(current) > self.__maxCacheTime:
224 keysToBeDeleted.append(key) 225 keysToBeDeleted.append(key)
225 for key in keysToBeDeleted: 226 for key in keysToBeDeleted:
226 self.remove(key) 227 self.remove(key)
227 228
228 self.__cacheTimer.start() 229 self.__cacheTimer.start()

eric ide

mercurial