more lru
diff --git a/lib/mako/util.py b/lib/mako/util.py index f42eec9..fa0b655 100644 --- a/lib/mako/util.py +++ b/lib/mako/util.py
@@ -74,6 +74,9 @@ item.timestamp = time.time() return item.value + def values(self): + return [i.value for i in dict.values(self)] + def __setitem__(self, key, value): item = dict.get(self, key) if item is None: @@ -85,7 +88,7 @@ def _manage_size(self): while len(self) > self.capacity + self.capacity * self.threshold: - bytime = self.values() + bytime = dict.values(self) bytime.sort(lambda a, b: cmp(b.timestamp, a.timestamp)) for item in bytime[self.capacity:]: try:
diff --git a/test/lru.py b/test/lru.py index 0ca4b25..67f3093 100644 --- a/test/lru.py +++ b/test/lru.py
@@ -44,37 +44,65 @@ size = 100 threshold = .5 all_elems = 2000 - hot_zone = range(30,100) + hot_zone = range(30,40) cache = LRUCache(size, threshold) + + # element to store class Element(object): def __init__(self, id): self.id = id + self.regets = 0 + + # return an element. we will favor ids in the relatively small + # "hot zone" 25% of the time. def get_elem(): if random.randint(1,4) == 1: return hot_zone[random.randint(0, len(hot_zone) - 1)] else: return random.randint(1, all_elems) + total = [0] + # request thread. def request_elem(): while True: + total[0] += 1 id = get_elem() try: elem = cache[id] + elem.regets += 1 except KeyError: - cache[id] = Element(id) + e = Element(id) + cache[id] = e + time.sleep(random.random() / 1000) for x in range(0,20): thread.start_new_thread(request_elem, ()) + + # assert size doesn't grow unbounded, doesnt shrink well below size for x in range(0,5): time.sleep(1) - #print "size:", len(cache) + print "size:", len(cache) assert len(cache) < size + size * threshold * 2 assert len(cache) > size - (size * .1) - total = 0 - for h in hot_zone: - if h in cache: - total += 1 - #print "total hot zone in cache: " , total, "of", len(hot_zone) + + # computs the average number of times a range of elements were "reused", + # i.e. without being removed from the cache. + def average_regets_in_range(start, end): + elem = [e for e in cache.values() if e.id >= start and e.id <= end] + if len(elem) == 0: + return 0 + avg = sum([e.regets for e in elem]) / len(elem) + return avg + + hotzone_avg = average_regets_in_range(30, 40) + control_avg = average_regets_in_range(450,760) + total_avg = average_regets_in_range(0, 2000) + + # hotzone should be way above the others + print "total fetches", total[0], "hotzone", hotzone_avg, "control", control_avg, "total", total_avg + + assert hotzone_avg > total_avg * 5 > control_avg * 5 + if __name__ == "__main__": unittest.main()