diff --git a/synapse/util/caches/expiringcache.py b/synapse/util/caches/expiringcache.py
index cddf1ed515..2726b67b6d 100644
--- a/synapse/util/caches/expiringcache.py
+++ b/synapse/util/caches/expiringcache.py
@@ -18,6 +18,7 @@ from collections import OrderedDict
from six import iteritems, itervalues
+from synapse.config import cache as cache_config
from synapse.metrics.background_process_metrics import run_as_background_process
from synapse.util.caches import register_cache
@@ -51,15 +52,16 @@ class ExpiringCache(object):
an item on access. Defaults to False.
iterable (bool): If true, the size is calculated by summing the
sizes of all entries, rather than the number of entries.
-
"""
self._cache_name = cache_name
+ self._original_max_size = max_len
+
+ self._max_size = int(max_len * cache_config.properties.default_factor_size)
+
self._clock = clock
- self._max_len = max_len
self._expiry_ms = expiry_ms
-
self._reset_expiry_on_get = reset_expiry_on_get
self._cache = OrderedDict()
@@ -82,9 +84,11 @@ class ExpiringCache(object):
def __setitem__(self, key, value):
now = self._clock.time_msec()
self._cache[key] = _CacheEntry(now, value)
+ self.evict()
+ def evict(self):
# Evict if there are now too many items
- while self._max_len and len(self) > self._max_len:
+ while self._max_size and len(self) > self._max_size:
_key, value = self._cache.popitem(last=False)
if self.iterable:
self.metrics.inc_evictions(len(value.value))
@@ -170,6 +174,23 @@ class ExpiringCache(object):
else:
return len(self._cache)
+ def set_cache_factor(self, factor: float) -> bool:
+ """
+ Set the cache factor for this individual cache.
+
+ This will trigger a resize if it changes, which may require evicting
+ items from the cache.
+
+ Returns:
+ bool: Whether the cache changed size or not.
+ """
+ new_size = int(self._original_max_size * factor)
+ if new_size != self._max_size:
+ self._max_size = new_size
+ self.evict()
+ return True
+ return False
+
class _CacheEntry(object):
__slots__ = ["time", "value"]
|