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

Commit a2d7195

Browse files
author
David Robertson
authored
Track why we're evicting from caches (#10829)
So we can see distinguish between "evicting because the cache is too big" and "evicting because the cache entries haven't been recently used".
1 parent 51e2db3 commit a2d7195

File tree

4 files changed

+31
-15
lines changed

4 files changed

+31
-15
lines changed

changelog.d/10829.misc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Track cache eviction rates more finely in Prometheus' monitoring.

synapse/util/caches/__init__.py

+23-8
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
15-
15+
import collections
1616
import logging
17+
import typing
18+
from enum import Enum, auto
1719
from sys import intern
1820
from typing import Callable, Dict, Optional, Sized
1921

@@ -34,7 +36,7 @@
3436

3537
cache_size = Gauge("synapse_util_caches_cache:size", "", ["name"])
3638
cache_hits = Gauge("synapse_util_caches_cache:hits", "", ["name"])
37-
cache_evicted = Gauge("synapse_util_caches_cache:evicted_size", "", ["name"])
39+
cache_evicted = Gauge("synapse_util_caches_cache:evicted_size", "", ["name", "reason"])
3840
cache_total = Gauge("synapse_util_caches_cache:total", "", ["name"])
3941
cache_max_size = Gauge("synapse_util_caches_cache_max_size", "", ["name"])
4042
cache_memory_usage = Gauge(
@@ -46,11 +48,16 @@
4648
response_cache_size = Gauge("synapse_util_caches_response_cache:size", "", ["name"])
4749
response_cache_hits = Gauge("synapse_util_caches_response_cache:hits", "", ["name"])
4850
response_cache_evicted = Gauge(
49-
"synapse_util_caches_response_cache:evicted_size", "", ["name"]
51+
"synapse_util_caches_response_cache:evicted_size", "", ["name", "reason"]
5052
)
5153
response_cache_total = Gauge("synapse_util_caches_response_cache:total", "", ["name"])
5254

5355

56+
class EvictionReason(Enum):
57+
size = auto()
58+
time = auto()
59+
60+
5461
@attr.s(slots=True)
5562
class CacheMetric:
5663

@@ -61,7 +68,9 @@ class CacheMetric:
6168

6269
hits = attr.ib(default=0)
6370
misses = attr.ib(default=0)
64-
evicted_size = attr.ib(default=0)
71+
eviction_size_by_reason: typing.Counter[EvictionReason] = attr.ib(
72+
factory=collections.Counter
73+
)
6574
memory_usage = attr.ib(default=None)
6675

6776
def inc_hits(self) -> None:
@@ -70,8 +79,8 @@ def inc_hits(self) -> None:
7079
def inc_misses(self) -> None:
7180
self.misses += 1
7281

73-
def inc_evictions(self, size: int = 1) -> None:
74-
self.evicted_size += size
82+
def inc_evictions(self, reason: EvictionReason, size: int = 1) -> None:
83+
self.eviction_size_by_reason[reason] += size
7584

7685
def inc_memory_usage(self, memory: int) -> None:
7786
if self.memory_usage is None:
@@ -94,14 +103,20 @@ def collect(self) -> None:
94103
if self._cache_type == "response_cache":
95104
response_cache_size.labels(self._cache_name).set(len(self._cache))
96105
response_cache_hits.labels(self._cache_name).set(self.hits)
97-
response_cache_evicted.labels(self._cache_name).set(self.evicted_size)
106+
for reason in EvictionReason:
107+
response_cache_evicted.labels(self._cache_name, reason.name).set(
108+
self.eviction_size_by_reason[reason]
109+
)
98110
response_cache_total.labels(self._cache_name).set(
99111
self.hits + self.misses
100112
)
101113
else:
102114
cache_size.labels(self._cache_name).set(len(self._cache))
103115
cache_hits.labels(self._cache_name).set(self.hits)
104-
cache_evicted.labels(self._cache_name).set(self.evicted_size)
116+
for reason in EvictionReason:
117+
cache_evicted.labels(self._cache_name, reason.name).set(
118+
self.eviction_size_by_reason[reason]
119+
)
105120
cache_total.labels(self._cache_name).set(self.hits + self.misses)
106121
if getattr(self._cache, "max_size", None):
107122
cache_max_size.labels(self._cache_name).set(self._cache.max_size)

synapse/util/caches/expiringcache.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from synapse.config import cache as cache_config
2323
from synapse.metrics.background_process_metrics import run_as_background_process
2424
from synapse.util import Clock
25-
from synapse.util.caches import register_cache
25+
from synapse.util.caches import EvictionReason, register_cache
2626

2727
logger = logging.getLogger(__name__)
2828

@@ -98,9 +98,9 @@ def evict(self) -> None:
9898
while self._max_size and len(self) > self._max_size:
9999
_key, value = self._cache.popitem(last=False)
100100
if self.iterable:
101-
self.metrics.inc_evictions(len(value.value))
101+
self.metrics.inc_evictions(EvictionReason.size, len(value.value))
102102
else:
103-
self.metrics.inc_evictions()
103+
self.metrics.inc_evictions(EvictionReason.size)
104104

105105
def __getitem__(self, key: KT) -> VT:
106106
try:
@@ -175,9 +175,9 @@ def _prune_cache(self) -> None:
175175
for k in keys_to_delete:
176176
value = self._cache.pop(k)
177177
if self.iterable:
178-
self.metrics.inc_evictions(len(value.value))
178+
self.metrics.inc_evictions(EvictionReason.time, len(value.value))
179179
else:
180-
self.metrics.inc_evictions()
180+
self.metrics.inc_evictions(EvictionReason.time)
181181

182182
logger.debug(
183183
"[%s] _prune_cache before: %d, after len: %d",

synapse/util/caches/lrucache.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
from synapse.config import cache as cache_config
4141
from synapse.metrics.background_process_metrics import wrap_as_background_process
4242
from synapse.util import Clock, caches
43-
from synapse.util.caches import CacheMetric, register_cache
43+
from synapse.util.caches import CacheMetric, EvictionReason, register_cache
4444
from synapse.util.caches.treecache import TreeCache, iterate_tree_cache_entry
4545
from synapse.util.linked_list import ListNode
4646

@@ -403,7 +403,7 @@ def evict() -> None:
403403
evicted_len = delete_node(node)
404404
cache.pop(node.key, None)
405405
if metrics:
406-
metrics.inc_evictions(evicted_len)
406+
metrics.inc_evictions(EvictionReason.size, evicted_len)
407407

408408
def synchronized(f: FT) -> FT:
409409
@wraps(f)

0 commit comments

Comments
 (0)