-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Limit how often GC happens by time. #9902
Changes from all commits
79627b3
351f886
d3a6e38
bd04fb6
43c9acd
b5169b6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| Add limits to how often Synapse will GC, ensuring that large servers do not end up GC thrashing if `gc_thresholds` has not been correctly set. |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -535,6 +535,13 @@ def collect(self): | |||||
|
|
||||||
| REGISTRY.register(ReactorLastSeenMetric()) | ||||||
|
|
||||||
| # The minimum time in seconds between GCs for each generation, regardless of the current GC | ||||||
| # thresholds and counts. | ||||||
| MIN_TIME_BETWEEN_GCS = (1.0, 10.0, 30.0) | ||||||
|
|
||||||
| # The time (in seconds since the epoch) of the last time we did a GC for each generation. | ||||||
| _last_gc = [0.0, 0.0, 0.0] | ||||||
|
|
||||||
|
|
||||||
| def runUntilCurrentTimer(reactor, func): | ||||||
| @functools.wraps(func) | ||||||
|
|
@@ -575,11 +582,16 @@ def f(*args, **kwargs): | |||||
| return ret | ||||||
|
|
||||||
| # Check if we need to do a manual GC (since its been disabled), and do | ||||||
| # one if necessary. | ||||||
| # one if necessary. Note we go in reverse order as e.g. a gen 1 GC may | ||||||
| # promote an object into gen 2, and we don't want to handle the same | ||||||
| # object multiple times. | ||||||
| threshold = gc.get_threshold() | ||||||
| counts = gc.get_count() | ||||||
| for i in (2, 1, 0): | ||||||
| if threshold[i] < counts[i]: | ||||||
| # We check if we need to do one based on a straightforward | ||||||
| # comparison between the threshold and count. We also do an extra | ||||||
| # check to make sure that we don't a GC too often. | ||||||
| if threshold[i] < counts[i] and MIN_TIME_BETWEEN_GCS[i] < end - _last_gc[i]: | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can become out-of-bounds if someone specifies
Suggested change
I'm also wary of mutating a "constant" like this, because it can give mixed signals in the code.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, mutating is a bit icky, but I can't think of a better way of injecting the values at this point.
We check for the right format in the config, so I think its fine that this explodes if a developer messes up and sets it incorrectly. |
||||||
| if i == 0: | ||||||
| logger.debug("Collecting gc %d", i) | ||||||
| else: | ||||||
|
|
@@ -589,6 +601,8 @@ def f(*args, **kwargs): | |||||
| unreachable = gc.collect(i) | ||||||
| end = time.time() | ||||||
|
|
||||||
| _last_gc[i] = end | ||||||
|
|
||||||
| gc_time.labels(i).observe(end - start) | ||||||
| gc_unreachable.labels(i).set(unreachable) | ||||||
|
|
||||||
|
|
||||||
Uh oh!
There was an error while loading. Please reload this page.