add tests for individual cache sizing, and fix up the individual cache sizing logic that got deleted when resizing-on-the-fly did

anoa/temp_working_cache_config
Amber H. Brown 2020-02-17 17:47:56 +11:00
parent 4aeb6fbe2c
commit 5f508e728a
2 changed files with 91 additions and 5 deletions

View File

@ -39,20 +39,35 @@ _DEFAULT_CONFIG = """\
#
"""
# Callback to ensure that all caches are the correct size, registered when the
# configuration has been loaded.
_ENSURE_CORRECT_CACHE_SIZING = None
def add_resizable_cache(cache_name, cache_resize_callback):
_CACHES[cache_name.lower()] = cache_resize_callback
cache_resize_callback(DEFAULT_CACHE_SIZE_FACTOR)
if _ENSURE_CORRECT_CACHE_SIZING:
_ENSURE_CORRECT_CACHE_SIZING()
class CacheConfig(Config):
section = "caches"
_environ = os.environ
@staticmethod
def _reset():
global DEFAULT_CACHE_SIZE_FACTOR
global _ENSURE_CORRECT_CACHE_SIZING
DEFAULT_CACHE_SIZE_FACTOR = float(os.environ.get(_CACHE_PREFIX, 0.5))
_ENSURE_CORRECT_CACHE_SIZING = None
_CACHES.clear()
def read_config(self, config, **kwargs):
self.event_cache_size = self.parse_size(config.get("event_cache_size", "10K"))
global DEFAULT_CACHE_SIZE_FACTOR
global _ENSURE_CORRECT_CACHE_SIZING
cache_config = config.get("caches", {})
@ -79,9 +94,7 @@ class CacheConfig(Config):
individual_factors.update(individual_factors_config)
self.cache_factors = defaultdict(
lambda: self.global_factor
) # type: DefaultDict[str, float]
self.cache_factors = dict() # type: Dict[str, float]
for cache, factor in individual_factors.items():
if not isinstance(factor, (int, float)):
@ -89,3 +102,12 @@ class CacheConfig(Config):
"caches.per_cache_factors.%s must be a number" % (cache.lower(),)
)
self.cache_factors[cache.lower()] = factor
# Register the global callback so that the individual cache sizes get set.
def ensure_cache_sizes():
for cache_name, callback in _CACHES.items():
new_factor = self.cache_factors.get(cache_name, self.global_factor)
callback(new_factor)
_ENSURE_CORRECT_CACHE_SIZING = ensure_cache_sizes
_ENSURE_CORRECT_CACHE_SIZING()

View File

@ -14,7 +14,8 @@
# limitations under the License.
from synapse.config._base import Config, RootConfig
from synapse.config.cache import CacheConfig
from synapse.config.cache import CacheConfig, add_resizable_cache
from synapse.util.caches.lrucache import LruCache
from tests.unittest import TestCase
@ -28,6 +29,9 @@ class TestConfig(RootConfig):
class CacheConfigTests(TestCase):
def setUp(self):
CacheConfig._reset()
def test_individual_caches_from_environ(self):
"""
Individual cache factors will be loaded from the environment.
@ -59,3 +63,63 @@ class CacheConfigTests(TestCase):
dict(t.caches.cache_factors),
{"foo": 2.0, "bar": 3.0, "something_or_other": 2.0},
)
def test_individual_instantiated_before_config_load(self):
"""
If a cache is instantiated before the config is read, it will be given
the default cache size in the interim, and then resized once the config
is loaded.
"""
cache = LruCache(100)
add_resizable_cache("foo", cache.set_cache_factor)
self.assertEqual(cache.max_size, 50)
config = {"caches": {"per_cache_factors": {"foo": 3}}}
t = TestConfig()
t.read_config(config, config_dir_path="", data_dir_path="")
self.assertEqual(cache.max_size, 300)
def test_individual_instantiated_after_config_load(self):
"""
If a cache is instantiated after the config is read, it will be
immediately resized to the correct size given the per_cache_factor if
there is one.
"""
config = {"caches": {"per_cache_factors": {"foo": 2}}}
t = TestConfig()
t.read_config(config, config_dir_path="", data_dir_path="")
cache = LruCache(100)
add_resizable_cache("foo", cache.set_cache_factor)
self.assertEqual(cache.max_size, 200)
def test_global_instantiated_before_config_load(self):
"""
If a cache is instantiated before the config is read, it will be given
the default cache size in the interim, and then resized to the new
default cache size once the config is loaded.
"""
cache = LruCache(100)
add_resizable_cache("foo", cache.set_cache_factor)
self.assertEqual(cache.max_size, 50)
config = {"caches": {"global_factor": 4}}
t = TestConfig()
t.read_config(config, config_dir_path="", data_dir_path="")
self.assertEqual(cache.max_size, 400)
def test_global_instantiated_after_config_load(self):
"""
If a cache is instantiated after the config is read, it will be
immediately resized to the correct size given the global factor if there
is no per-cache factor.
"""
config = {"caches": {"global_factor": 1.5}}
t = TestConfig()
t.read_config(config, config_dir_path="", data_dir_path="")
cache = LruCache(100)
add_resizable_cache("foo", cache.set_cache_factor)
self.assertEqual(cache.max_size, 150)