Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit 7a58732

Browse files
authored
Add support for evicting cache entries based on last access time. (#10205)
1 parent 10671da commit 7a58732

File tree

9 files changed

+485
-95
lines changed

9 files changed

+485
-95
lines changed

changelog.d/10205.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add support for evicting cache entries based on last access time.

docs/sample_config.yaml

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -673,35 +673,41 @@ retention:
673673
#event_cache_size: 10K
674674

675675
caches:
676-
# Controls the global cache factor, which is the default cache factor
677-
# for all caches if a specific factor for that cache is not otherwise
678-
# set.
679-
#
680-
# This can also be set by the "SYNAPSE_CACHE_FACTOR" environment
681-
# variable. Setting by environment variable takes priority over
682-
# setting through the config file.
683-
#
684-
# Defaults to 0.5, which will half the size of all caches.
685-
#
686-
#global_factor: 1.0
676+
# Controls the global cache factor, which is the default cache factor
677+
# for all caches if a specific factor for that cache is not otherwise
678+
# set.
679+
#
680+
# This can also be set by the "SYNAPSE_CACHE_FACTOR" environment
681+
# variable. Setting by environment variable takes priority over
682+
# setting through the config file.
683+
#
684+
# Defaults to 0.5, which will half the size of all caches.
685+
#
686+
#global_factor: 1.0
687687

688-
# A dictionary of cache name to cache factor for that individual
689-
# cache. Overrides the global cache factor for a given cache.
690-
#
691-
# These can also be set through environment variables comprised
692-
# of "SYNAPSE_CACHE_FACTOR_" + the name of the cache in capital
693-
# letters and underscores. Setting by environment variable
694-
# takes priority over setting through the config file.
695-
# Ex. SYNAPSE_CACHE_FACTOR_GET_USERS_WHO_SHARE_ROOM_WITH_USER=2.0
696-
#
697-
# Some caches have '*' and other characters that are not
698-
# alphanumeric or underscores. These caches can be named with or
699-
# without the special characters stripped. For example, to specify
700-
# the cache factor for `*stateGroupCache*` via an environment
701-
# variable would be `SYNAPSE_CACHE_FACTOR_STATEGROUPCACHE=2.0`.
702-
#
703-
per_cache_factors:
704-
#get_users_who_share_room_with_user: 2.0
688+
# A dictionary of cache name to cache factor for that individual
689+
# cache. Overrides the global cache factor for a given cache.
690+
#
691+
# These can also be set through environment variables comprised
692+
# of "SYNAPSE_CACHE_FACTOR_" + the name of the cache in capital
693+
# letters and underscores. Setting by environment variable
694+
# takes priority over setting through the config file.
695+
# Ex. SYNAPSE_CACHE_FACTOR_GET_USERS_WHO_SHARE_ROOM_WITH_USER=2.0
696+
#
697+
# Some caches have '*' and other characters that are not
698+
# alphanumeric or underscores. These caches can be named with or
699+
# without the special characters stripped. For example, to specify
700+
# the cache factor for `*stateGroupCache*` via an environment
701+
# variable would be `SYNAPSE_CACHE_FACTOR_STATEGROUPCACHE=2.0`.
702+
#
703+
per_cache_factors:
704+
#get_users_who_share_room_with_user: 2.0
705+
706+
# Controls how long an entry can be in a cache without having been
707+
# accessed before being evicted. Defaults to None, which means
708+
# entries are never evicted based on time.
709+
#
710+
#expiry_time: 30m
705711

706712

707713
## Database ##

mypy.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ files =
7575
synapse/util/daemonize.py,
7676
synapse/util/hash.py,
7777
synapse/util/iterutils.py,
78+
synapse/util/linked_list.py,
7879
synapse/util/metrics.py,
7980
synapse/util/macaroons.py,
8081
synapse/util/module_loader.py,

synapse/app/_base.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import sys
2222
import traceback
2323
import warnings
24-
from typing import Awaitable, Callable, Iterable
24+
from typing import TYPE_CHECKING, Awaitable, Callable, Iterable
2525

2626
from cryptography.utils import CryptographyDeprecationWarning
2727
from typing_extensions import NoReturn
@@ -41,10 +41,14 @@
4141
from synapse.logging.context import PreserveLoggingContext
4242
from synapse.metrics.background_process_metrics import wrap_as_background_process
4343
from synapse.metrics.jemalloc import setup_jemalloc_stats
44+
from synapse.util.caches.lrucache import setup_expire_lru_cache_entries
4445
from synapse.util.daemonize import daemonize_process
4546
from synapse.util.rlimit import change_resource_limit
4647
from synapse.util.versionstring import get_version_string
4748

49+
if TYPE_CHECKING:
50+
from synapse.server import HomeServer
51+
4852
logger = logging.getLogger(__name__)
4953

5054
# list of tuples of function, args list, kwargs dict
@@ -312,7 +316,7 @@ def refresh_certificate(hs):
312316
logger.info("Context factories updated.")
313317

314318

315-
async def start(hs: "synapse.server.HomeServer"):
319+
async def start(hs: "HomeServer"):
316320
"""
317321
Start a Synapse server or worker.
318322
@@ -365,6 +369,9 @@ def run_sighup(*args, **kwargs):
365369

366370
load_legacy_spam_checkers(hs)
367371

372+
# If we've configured an expiry time for caches, start the background job now.
373+
setup_expire_lru_cache_entries(hs)
374+
368375
# It is now safe to start your Synapse.
369376
hs.start_listening()
370377
hs.get_datastore().db_pool.start_profiling()

synapse/config/_base.pyi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ from synapse.config import (
55
api,
66
appservice,
77
auth,
8+
cache,
89
captcha,
910
cas,
1011
consent,
@@ -88,6 +89,7 @@ class RootConfig:
8889
tracer: tracer.TracerConfig
8990
redis: redis.RedisConfig
9091
modules: modules.ModulesConfig
92+
caches: cache.CacheConfig
9193
federation: federation.FederationConfig
9294

9395
config_classes: List = ...

synapse/config/cache.py

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -116,35 +116,41 @@ def generate_config_section(self, **kwargs):
116116
#event_cache_size: 10K
117117
118118
caches:
119-
# Controls the global cache factor, which is the default cache factor
120-
# for all caches if a specific factor for that cache is not otherwise
121-
# set.
122-
#
123-
# This can also be set by the "SYNAPSE_CACHE_FACTOR" environment
124-
# variable. Setting by environment variable takes priority over
125-
# setting through the config file.
126-
#
127-
# Defaults to 0.5, which will half the size of all caches.
128-
#
129-
#global_factor: 1.0
130-
131-
# A dictionary of cache name to cache factor for that individual
132-
# cache. Overrides the global cache factor for a given cache.
133-
#
134-
# These can also be set through environment variables comprised
135-
# of "SYNAPSE_CACHE_FACTOR_" + the name of the cache in capital
136-
# letters and underscores. Setting by environment variable
137-
# takes priority over setting through the config file.
138-
# Ex. SYNAPSE_CACHE_FACTOR_GET_USERS_WHO_SHARE_ROOM_WITH_USER=2.0
139-
#
140-
# Some caches have '*' and other characters that are not
141-
# alphanumeric or underscores. These caches can be named with or
142-
# without the special characters stripped. For example, to specify
143-
# the cache factor for `*stateGroupCache*` via an environment
144-
# variable would be `SYNAPSE_CACHE_FACTOR_STATEGROUPCACHE=2.0`.
145-
#
146-
per_cache_factors:
147-
#get_users_who_share_room_with_user: 2.0
119+
# Controls the global cache factor, which is the default cache factor
120+
# for all caches if a specific factor for that cache is not otherwise
121+
# set.
122+
#
123+
# This can also be set by the "SYNAPSE_CACHE_FACTOR" environment
124+
# variable. Setting by environment variable takes priority over
125+
# setting through the config file.
126+
#
127+
# Defaults to 0.5, which will half the size of all caches.
128+
#
129+
#global_factor: 1.0
130+
131+
# A dictionary of cache name to cache factor for that individual
132+
# cache. Overrides the global cache factor for a given cache.
133+
#
134+
# These can also be set through environment variables comprised
135+
# of "SYNAPSE_CACHE_FACTOR_" + the name of the cache in capital
136+
# letters and underscores. Setting by environment variable
137+
# takes priority over setting through the config file.
138+
# Ex. SYNAPSE_CACHE_FACTOR_GET_USERS_WHO_SHARE_ROOM_WITH_USER=2.0
139+
#
140+
# Some caches have '*' and other characters that are not
141+
# alphanumeric or underscores. These caches can be named with or
142+
# without the special characters stripped. For example, to specify
143+
# the cache factor for `*stateGroupCache*` via an environment
144+
# variable would be `SYNAPSE_CACHE_FACTOR_STATEGROUPCACHE=2.0`.
145+
#
146+
per_cache_factors:
147+
#get_users_who_share_room_with_user: 2.0
148+
149+
# Controls how long an entry can be in a cache without having been
150+
# accessed before being evicted. Defaults to None, which means
151+
# entries are never evicted based on time.
152+
#
153+
#expiry_time: 30m
148154
"""
149155

150156
def read_config(self, config, **kwargs):
@@ -200,6 +206,12 @@ def read_config(self, config, **kwargs):
200206
e.message # noqa: B306, DependencyException.message is a property
201207
)
202208

209+
expiry_time = cache_config.get("expiry_time")
210+
if expiry_time:
211+
self.expiry_time_msec = self.parse_duration(expiry_time)
212+
else:
213+
self.expiry_time_msec = None
214+
203215
# Resize all caches (if necessary) with the new factors we've loaded
204216
self.resize_all_caches()
205217

0 commit comments

Comments
 (0)