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

Add support for evicting cache entries based on last access time. #10205

Merged
merged 26 commits into from
Jul 5, 2021
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
700af7a
Add global cache list.
erikjohnston May 27, 2021
eaaee81
Add function to clean up old cache entries
erikjohnston Jun 18, 2021
811aa3f
Add config
erikjohnston Jun 18, 2021
9f62fdf
Newsfile
erikjohnston Jun 18, 2021
7ba719c
Update memory usage
erikjohnston Jun 18, 2021
01afcf6
Only use GLOBAL_LIST if time based eviction is enabled
erikjohnston Jun 18, 2021
a4657df
Add test
erikjohnston Jun 21, 2021
f72ed26
Reduce size overhead of new functionality
erikjohnston Jun 21, 2021
a52eb83
Merge remote-tracking branch 'origin/develop' into erikj/global_cache…
erikjohnston Jun 21, 2021
b314dfc
Fix 'caches' identation
erikjohnston Jun 24, 2021
6600a7c
Remove superflouous default None
erikjohnston Jun 24, 2021
e03a81c
Remove redundant setting of global_list_node
erikjohnston Jun 24, 2021
939ce8d
Make new attributes private
erikjohnston Jun 24, 2021
ecab588
Fixup comments
erikjohnston Jun 24, 2021
4181e1d
Improve comments and error handling when walking the graphs
erikjohnston Jun 24, 2021
7d865a1
Fix up names and comments in _expire_old_entries
erikjohnston Jun 24, 2021
be2667d
Add explicit `create_root_node`
erikjohnston Jun 24, 2021
1da43cb
Refactor so _ListNode doesn't take Clock
erikjohnston Jun 24, 2021
73064e0
Update comment about shared weakref
erikjohnston Jun 24, 2021
dd6dfdd
Remove superfluous _CacheEntry protocol
erikjohnston Jun 24, 2021
df40007
Add lock to ensure list mutation is thread safe
erikjohnston Jun 25, 2021
a2f5c11
Merge remote-tracking branch 'origin/develop' into erikj/global_cache…
erikjohnston Jul 5, 2021
df298d1
Fix indent
erikjohnston Jul 5, 2021
c5f19d9
Review comments
erikjohnston Jul 5, 2021
408e7c3
Move _ListNode to its own file
erikjohnston Jul 5, 2021
2f3480e
Apply suggestions from code review
erikjohnston Jul 5, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/10205.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add support for evicting cache entries based on last access time.
62 changes: 34 additions & 28 deletions docs/sample_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -673,35 +673,41 @@ retention:
#event_cache_size: 10K

caches:
# Controls the global cache factor, which is the default cache factor
# for all caches if a specific factor for that cache is not otherwise
# set.
#
# This can also be set by the "SYNAPSE_CACHE_FACTOR" environment
# variable. Setting by environment variable takes priority over
# setting through the config file.
#
# Defaults to 0.5, which will half the size of all caches.
#
#global_factor: 1.0
# Controls the global cache factor, which is the default cache factor
# for all caches if a specific factor for that cache is not otherwise
# set.
#
# This can also be set by the "SYNAPSE_CACHE_FACTOR" environment
# variable. Setting by environment variable takes priority over
# setting through the config file.
#
# Defaults to 0.5, which will half the size of all caches.
#
#global_factor: 1.0

# A dictionary of cache name to cache factor for that individual
# cache. Overrides the global cache factor for a given cache.
#
# These can also be set through environment variables comprised
# of "SYNAPSE_CACHE_FACTOR_" + the name of the cache in capital
# letters and underscores. Setting by environment variable
# takes priority over setting through the config file.
# Ex. SYNAPSE_CACHE_FACTOR_GET_USERS_WHO_SHARE_ROOM_WITH_USER=2.0
#
# Some caches have '*' and other characters that are not
# alphanumeric or underscores. These caches can be named with or
# without the special characters stripped. For example, to specify
# the cache factor for `*stateGroupCache*` via an environment
# variable would be `SYNAPSE_CACHE_FACTOR_STATEGROUPCACHE=2.0`.
#
per_cache_factors:
#get_users_who_share_room_with_user: 2.0
# A dictionary of cache name to cache factor for that individual
# cache. Overrides the global cache factor for a given cache.
#
# These can also be set through environment variables comprised
# of "SYNAPSE_CACHE_FACTOR_" + the name of the cache in capital
# letters and underscores. Setting by environment variable
# takes priority over setting through the config file.
# Ex. SYNAPSE_CACHE_FACTOR_GET_USERS_WHO_SHARE_ROOM_WITH_USER=2.0
#
# Some caches have '*' and other characters that are not
# alphanumeric or underscores. These caches can be named with or
# without the special characters stripped. For example, to specify
# the cache factor for `*stateGroupCache*` via an environment
# variable would be `SYNAPSE_CACHE_FACTOR_STATEGROUPCACHE=2.0`.
#
per_cache_factors:
#get_users_who_share_room_with_user: 2.0

# Controls how long an entry can be in a cache without having been
# accessed before being evicted. Defaults to None, which means
# entries are never evicted based on time.
#
#expiry_time: 30m


## Database ##
Expand Down
11 changes: 9 additions & 2 deletions synapse/app/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import sys
import traceback
import warnings
from typing import Awaitable, Callable, Iterable
from typing import TYPE_CHECKING, Awaitable, Callable, Iterable

from cryptography.utils import CryptographyDeprecationWarning
from typing_extensions import NoReturn
Expand All @@ -41,10 +41,14 @@
from synapse.logging.context import PreserveLoggingContext
from synapse.metrics.background_process_metrics import wrap_as_background_process
from synapse.metrics.jemalloc import setup_jemalloc_stats
from synapse.util.caches.lrucache import setup_expire_lru_cache_entries
from synapse.util.daemonize import daemonize_process
from synapse.util.rlimit import change_resource_limit
from synapse.util.versionstring import get_version_string

if TYPE_CHECKING:
from synapse.server import HomeServer

logger = logging.getLogger(__name__)

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


async def start(hs: "synapse.server.HomeServer"):
async def start(hs: "HomeServer"):
"""
Start a Synapse server or worker.

Expand Down Expand Up @@ -365,6 +369,9 @@ def run_sighup(*args, **kwargs):

load_legacy_spam_checkers(hs)

# If we've configured an expiry time for caches, start the background job now.
setup_expire_lru_cache_entries(hs)

# It is now safe to start your Synapse.
hs.start_listening()
hs.get_datastore().db_pool.start_profiling()
Expand Down
2 changes: 2 additions & 0 deletions synapse/config/_base.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ from synapse.config import (
api,
appservice,
auth,
cache,
captcha,
cas,
consent,
Expand Down Expand Up @@ -88,6 +89,7 @@ class RootConfig:
tracer: tracer.TracerConfig
redis: redis.RedisConfig
modules: modules.ModulesConfig
caches: cache.CacheConfig
federation: federation.FederationConfig

config_classes: List = ...
Expand Down
70 changes: 41 additions & 29 deletions synapse/config/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,35 +116,41 @@ def generate_config_section(self, **kwargs):
#event_cache_size: 10K

caches:
# Controls the global cache factor, which is the default cache factor
# for all caches if a specific factor for that cache is not otherwise
# set.
#
# This can also be set by the "SYNAPSE_CACHE_FACTOR" environment
# variable. Setting by environment variable takes priority over
# setting through the config file.
#
# Defaults to 0.5, which will half the size of all caches.
#
#global_factor: 1.0

# A dictionary of cache name to cache factor for that individual
# cache. Overrides the global cache factor for a given cache.
#
# These can also be set through environment variables comprised
# of "SYNAPSE_CACHE_FACTOR_" + the name of the cache in capital
# letters and underscores. Setting by environment variable
# takes priority over setting through the config file.
# Ex. SYNAPSE_CACHE_FACTOR_GET_USERS_WHO_SHARE_ROOM_WITH_USER=2.0
#
# Some caches have '*' and other characters that are not
# alphanumeric or underscores. These caches can be named with or
# without the special characters stripped. For example, to specify
# the cache factor for `*stateGroupCache*` via an environment
# variable would be `SYNAPSE_CACHE_FACTOR_STATEGROUPCACHE=2.0`.
#
per_cache_factors:
#get_users_who_share_room_with_user: 2.0
# Controls the global cache factor, which is the default cache factor
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style guide says "use two-space indents".

# for all caches if a specific factor for that cache is not otherwise
# set.
#
# This can also be set by the "SYNAPSE_CACHE_FACTOR" environment
# variable. Setting by environment variable takes priority over
# setting through the config file.
#
# Defaults to 0.5, which will half the size of all caches.
#
#global_factor: 1.0

# A dictionary of cache name to cache factor for that individual
# cache. Overrides the global cache factor for a given cache.
#
# These can also be set through environment variables comprised
# of "SYNAPSE_CACHE_FACTOR_" + the name of the cache in capital
# letters and underscores. Setting by environment variable
# takes priority over setting through the config file.
# Ex. SYNAPSE_CACHE_FACTOR_GET_USERS_WHO_SHARE_ROOM_WITH_USER=2.0
#
# Some caches have '*' and other characters that are not
# alphanumeric or underscores. These caches can be named with or
# without the special characters stripped. For example, to specify
# the cache factor for `*stateGroupCache*` via an environment
# variable would be `SYNAPSE_CACHE_FACTOR_STATEGROUPCACHE=2.0`.
#
per_cache_factors:
#get_users_who_share_room_with_user: 2.0

# Controls how long an entry can be in a cache without having been
# accessed before being evicted. Defaults to None, which means
# entries are never evicted based on time.
#
#expiry_time: 30m
erikjohnston marked this conversation as resolved.
Show resolved Hide resolved
"""

def read_config(self, config, **kwargs):
Expand Down Expand Up @@ -200,6 +206,12 @@ def read_config(self, config, **kwargs):
e.message # noqa: B306, DependencyException.message is a property
)

expiry_time = cache_config.get("expiry_time")
if expiry_time:
self.expiry_time_msec = self.parse_duration(expiry_time)
else:
self.expiry_time_msec = None

# Resize all caches (if necessary) with the new factors we've loaded
self.resize_all_caches()

Expand Down
Loading