From f1f81221205cf2ec101f96234050569d6419fd6b Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 21 Jan 2016 19:16:25 +0000 Subject: Change LRUCache to be tree-based so we can delete subtrees. --- synapse/util/caches/descriptors.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'synapse/util/caches/descriptors.py') diff --git a/synapse/util/caches/descriptors.py b/synapse/util/caches/descriptors.py index 0033051849..af7bf15500 100644 --- a/synapse/util/caches/descriptors.py +++ b/synapse/util/caches/descriptors.py @@ -38,7 +38,7 @@ class Cache(object): def __init__(self, name, max_entries=1000, keylen=1, lru=True): if lru: - self.cache = LruCache(max_size=max_entries) + self.cache = LruCache(max_size=max_entries, keylen=keylen) self.max_entries = None else: self.cache = OrderedDict() @@ -99,6 +99,15 @@ class Cache(object): self.sequence += 1 self.cache.pop(key, None) + def invalidate_many(self, key): + self.check_thread() + if not isinstance(key, tuple): + raise TypeError( + "The cache key must be a tuple not %r" % (type(key),) + ) + self.sequence += 1 + self.cache.del_multi(key) + def invalidate_all(self): self.check_thread() self.sequence += 1 -- cgit 1.4.1 From 8acc5cb60f551f56815c60a33c36d6752f4b0967 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 22 Jan 2016 11:22:32 +0000 Subject: Add invalidate_many here too --- synapse/util/caches/descriptors.py | 1 + 1 file changed, 1 insertion(+) (limited to 'synapse/util/caches/descriptors.py') diff --git a/synapse/util/caches/descriptors.py b/synapse/util/caches/descriptors.py index af7bf15500..f4a2b4e590 100644 --- a/synapse/util/caches/descriptors.py +++ b/synapse/util/caches/descriptors.py @@ -209,6 +209,7 @@ class CacheDescriptor(object): wrapped.invalidate = self.cache.invalidate wrapped.invalidate_all = self.cache.invalidate_all + wrapped.invalidate_many = self.cache.invalidate_many wrapped.prefill = self.cache.prefill obj.__dict__[self.orig.__name__] = wrapped -- cgit 1.4.1 From 10f76dc5da47c49a4191d8113b3c0615224eb9fd Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 22 Jan 2016 12:10:33 +0000 Subject: Make LRU cache not default to treecache & add options to use it --- synapse/storage/event_push_actions.py | 2 +- synapse/util/caches/descriptors.py | 20 ++++++++++++++------ synapse/util/caches/lrucache.py | 9 +++++---- tests/util/test_lrucache.py | 3 ++- 4 files changed, 22 insertions(+), 12 deletions(-) (limited to 'synapse/util/caches/descriptors.py') diff --git a/synapse/storage/event_push_actions.py b/synapse/storage/event_push_actions.py index 6a212c630b..a05c4f84cf 100644 --- a/synapse/storage/event_push_actions.py +++ b/synapse/storage/event_push_actions.py @@ -53,7 +53,7 @@ class EventPushActionsStore(SQLBaseStore): f, ) - @cachedInlineCallbacks(num_args=3, lru=True) + @cachedInlineCallbacks(num_args=3, lru=True, tree=True) def get_unread_event_push_actions_by_room_for_user( self, room_id, user_id, last_read_event_id ): diff --git a/synapse/util/caches/descriptors.py b/synapse/util/caches/descriptors.py index f4a2b4e590..88e56e3302 100644 --- a/synapse/util/caches/descriptors.py +++ b/synapse/util/caches/descriptors.py @@ -17,6 +17,7 @@ import logging from synapse.util.async import ObservableDeferred from synapse.util import unwrapFirstError from synapse.util.caches.lrucache import LruCache +from synapse.util.caches.treecache import TreeCache from . import caches_by_name, DEBUG_CACHES, cache_counter @@ -36,9 +37,12 @@ _CacheSentinel = object() class Cache(object): - def __init__(self, name, max_entries=1000, keylen=1, lru=True): + def __init__(self, name, max_entries=1000, keylen=1, lru=True, tree=False): if lru: - self.cache = LruCache(max_size=max_entries, keylen=keylen) + cache_type = TreeCache if tree else dict + self.cache = LruCache( + max_size=max_entries, keylen=keylen, cache_type=cache_type + ) self.max_entries = None else: self.cache = OrderedDict() @@ -131,7 +135,7 @@ class CacheDescriptor(object): which can be used to insert values into the cache specifically, without calling the calculation function. """ - def __init__(self, orig, max_entries=1000, num_args=1, lru=True, + def __init__(self, orig, max_entries=1000, num_args=1, lru=True, tree=False, inlineCallbacks=False): self.orig = orig @@ -143,6 +147,7 @@ class CacheDescriptor(object): self.max_entries = max_entries self.num_args = num_args self.lru = lru + self.tree = tree self.arg_names = inspect.getargspec(orig).args[1:num_args+1] @@ -158,6 +163,7 @@ class CacheDescriptor(object): max_entries=self.max_entries, keylen=self.num_args, lru=self.lru, + tree=self.tree, ) def __get__(self, obj, objtype=None): @@ -331,21 +337,23 @@ class CacheListDescriptor(object): return wrapped -def cached(max_entries=1000, num_args=1, lru=True): +def cached(max_entries=1000, num_args=1, lru=True, tree=False): return lambda orig: CacheDescriptor( orig, max_entries=max_entries, num_args=num_args, - lru=lru + lru=lru, + tree=tree, ) -def cachedInlineCallbacks(max_entries=1000, num_args=1, lru=False): +def cachedInlineCallbacks(max_entries=1000, num_args=1, lru=False, tree=False): return lambda orig: CacheDescriptor( orig, max_entries=max_entries, num_args=num_args, lru=lru, + tree=tree, inlineCallbacks=True, ) diff --git a/synapse/util/caches/lrucache.py b/synapse/util/caches/lrucache.py index 0feceb298a..23e86ec110 100644 --- a/synapse/util/caches/lrucache.py +++ b/synapse/util/caches/lrucache.py @@ -17,8 +17,6 @@ from functools import wraps import threading -from synapse.util.caches.treecache import TreeCache - def enumerate_leaves(node, depth): if depth == 0: @@ -31,8 +29,8 @@ def enumerate_leaves(node, depth): class LruCache(object): """Least-recently-used cache.""" - def __init__(self, max_size, keylen): - cache = TreeCache() + def __init__(self, max_size, keylen, cache_type=dict): + cache = cache_type() self.size = 0 list_root = [] list_root[:] = [list_root, list_root, None, None] @@ -124,6 +122,9 @@ class LruCache(object): @synchronized def cache_del_multi(key): + """ + This will only work if constructed with cache_type=TreeCache + """ popped = cache.pop(key) if popped is None: return diff --git a/tests/util/test_lrucache.py b/tests/util/test_lrucache.py index fca2e98983..bcad1d4258 100644 --- a/tests/util/test_lrucache.py +++ b/tests/util/test_lrucache.py @@ -17,6 +17,7 @@ from .. import unittest from synapse.util.caches.lrucache import LruCache +from synapse.util.caches.treecache import TreeCache class LruCacheTestCase(unittest.TestCase): @@ -54,7 +55,7 @@ class LruCacheTestCase(unittest.TestCase): self.assertEquals(cache.pop(("key",)), None) def test_del_multi(self): - cache = LruCache(4, 2) + cache = LruCache(4, 2, cache_type=TreeCache) cache[("animal", "cat")] = "mew" cache[("animal", "dog")] = "woof" cache[("vehicles", "car")] = "vroom" -- cgit 1.4.1