@@ -254,9 +254,97 @@ same key value (though any number of concurrent threads might be busy loading
254
254
the resources associated with different keys).
255
255
256
256
257
+ Caching and stale entries
258
+ ==========================
259
+
260
+ There is another `AutoLRUCache`-like class provided by the LRU module,
261
+ which gives more control over timing out of entries than `AutoLRUCache` does.
262
+
263
+
264
+ >>> from darts.lib.utils.lru import DecayingLRUCache
265
+ >>> current_time = 0
266
+ >>> def tick():
267
+ ... global current_time
268
+ ... current_time += 1
269
+
270
+ Here, we defined a simple "clock". We could have used the system clock,
271
+ but roling our own here gives us more control over the notion of "time".
272
+ Now, let's define a simple cache entry:
273
+
274
+ >>> from collections import namedtuple
275
+ >>> Entry = namedtuple("Entry", "timestamp payload")
276
+ >>> def make_entry(payload):
277
+ ... return Entry(current_time, payload)
278
+
279
+ and a loader function
280
+
281
+ >>> def load(full_key):
282
+ ... print "Loading", full_key
283
+ ... return make_entry(u"Entry for %r" % (full_key,))
284
+
285
+ For the following parts, we consider an entry to be "too old", if it has
286
+ been created more then two "ticks" ago:
287
+
288
+ >>> def is_still_current(entry):
289
+ ... return current_time - entry.timestamp <= 2
290
+
291
+ Finally, we create another cache thingy
292
+
293
+ >>> cache = DecayingLRUCache(load, tester=is_still_current, capacity=3)
294
+
295
+ The `DecayingLRUCache` shows much of the same behaviour of the `AutoLRUCache`,
296
+ namely:
297
+
298
+ >>> cache.load(1)
299
+ Loading 1
300
+ Entry(timestamp=0, payload=u'Entry for 1')
301
+ >>> cache.load(2)
302
+ Loading 2
303
+ Entry(timestamp=0, payload=u'Entry for 2')
304
+ >>> cache.load(3)
305
+ Loading 3
306
+ Entry(timestamp=0, payload=u'Entry for 3')
307
+ >>> cache.load(4)
308
+ Loading 4
309
+ Entry(timestamp=0, payload=u'Entry for 4')
310
+ >>> cache.load(1)
311
+ Loading 1
312
+ Entry(timestamp=0, payload=u'Entry for 1')
313
+
314
+ The entry with key `1` had to be reloaded, since the cache has a capacity of
315
+ 3, and the old entry for `1` was evicted when the entry for `4` was loaded
316
+ and we needed to make room.
317
+
318
+ >>> cache.load(3)
319
+ Entry(timestamp=0, payload=u'Entry for 3')
320
+
321
+ Now, let's advance time
322
+
323
+ >>> tick()
324
+ >>> cache.load(3)
325
+ Entry(timestamp=0, payload=u'Entry for 3')
326
+
327
+ The entry is still available.
328
+
329
+ >>> tick()
330
+ >>> cache.load(3)
331
+ Entry(timestamp=0, payload=u'Entry for 3')
332
+ >>> tick()
333
+ >>> cache.load(3)
334
+ Loading 3
335
+ Entry(timestamp=3, payload=u'Entry for 3')
336
+
337
+ Note, that eviction is still based on LRU, not on the age test.
338
+
339
+
257
340
Change Log
258
341
==========
259
342
343
+ Version 0.4
344
+ ------------
345
+
346
+ Added class `DecayingLRUCache`
347
+
260
348
Version 0.3
261
349
------------
262
350
0 commit comments