# Add config option to control cyclic garbage collector strategy

**URL:** <https://discuss.python.org/t/add-config-option-to-control-cyclic-garbage-collector-strategy/66125>\
**Category:** Ideas\
**Created:** [September 29, 2024, 4:27pm UTC](https://discuss.python.org/t/add-config-option-to-control-cyclic-garbage-collector-strategy/66125 "2024-09-29T16:27:26Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![nas](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/nas/32/536_2.png) [@nas](https://discuss.python.org/u/nas)\
**Post date:** [September 29, 2024, 4:27pm UTC](https://discuss.python.org/t/add-config-option-to-control-cyclic-garbage-collector-strategy/66125/1 "2024-09-29T16:27:26Z")

</div>

I’m proposing to add the [PYTHON\_GC\_THRESHOLD](https://github.com/python/cpython/pull/124743) environment variable to more easily control the “aggressiveness” of the cyclic GC. The default for that setting, for the non-incremental GC, is 700. That is quite aggressive in that the young generation is collected frequently. I suspect many programs would work reliability and gain some performance by setting that threshold higher. Itamar did some internal testig at Meta and found that [14,000](https://discuss.python.org/t/incremental-gc-and-pushing-back-the-3-13-0-release/65285/7) seems like a better threshold but it causes some services to crash with an OOM error.

This kind of “tuning knob” is quite low level and I think it could be better to have a high level tuning knob. Say, something like `PYTHON_GC_STRATEGY`, with possible values:

- aggressive: set when you don’t care so much about spending extra time in the GC and want low peak memory use and prompt cleanup of resources like sockets and file descriptors. This would be similar to what we have as the default settings now.
- throughput: set when minimizing execution time is most important. You don’t care so much about peak memory use or prompt resource cleanup. This would be similar to the “server” setting that some other other languages have. I don’t like “server” as a name since sometimes I’m very memory constrained on containers or VMs and I would want the “aggressive” setting.
- latency: set when minimizing GC pause times is the most important objective. E.g. could be used by games that want to deliver a consistent FPS rate.
- balanced: this could become the default setting and kind of a mixture of all. I think it would be less aggressive than what’s in 3.12 (better throughput, slightly higher peak memory usage)

---

<div class="post-metadata">

**Author:** ![itamaro](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/itamaro/32/20137_2.png) [@itamaro](https://discuss.python.org/u/itamaro)\
**Post date:** [September 29, 2024, 5:45pm UTC](https://discuss.python.org/t/add-config-option-to-control-cyclic-garbage-collector-strategy/66125/2 "2024-09-29T17:45:57Z")

</div>

I like the idea in the context of how GC works in 3.10 & 3.12 (and maybe also 3.13?), but how applicable is it going to be with changes in GC (like adaptive thresholds, incremental gc, etc)?  
If these high level strategies are still meaningful with the coming changes in GC, that sounds like a good idea.

I tend to be hesitant about environment-variable-controlled knobs. From my experience, they tend to cause surprise in different subprocess scenarios (whether via multiprocessing, subprocesses using `sys.executable`, and subprocesses launching other flavors of child Python applications). These surprises appear in both directions (e.g. “I expected the child application to inherit the parent’s GC strategy but it didn’t”, and “I didn’t expect the child application to inherit the parent’s GC strategy but it did”).  
If possible to _also_ expose this via a `-X` flag, it could help with making the semantics more explicit (still leads to surprises, but fewer).

---

<div class="post-metadata">

**Author:** ![nas](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/nas/32/536_2.png) [@nas](https://discuss.python.org/u/nas)\
**Post date:** [September 29, 2024, 6:55pm UTC](https://discuss.python.org/t/add-config-option-to-control-cyclic-garbage-collector-strategy/66125/3 "2024-09-29T18:55:17Z")

</div>

Yes, it would be an `-X` flag as well as a function like `gc.set_strategy()`. All those ways to set it have different pros and cons. I didn’t do an `-X` option for my `PYTHON_GC_THRESHOLD` PR because I wanted to keep the code as simple as possible in case it can go into the 3.13 RC. If it does get merged, I would add an `-X` option to the ‘main’ version as well. And it should become part of the config struct, so you can set it if you are embedding Python.

> If these high level strategies are still meaningful with the coming changes in GC, that sounds like a good idea.

The idea of a higher level tuning knob is that it can do something sensible if the GC logic is changed significantly in an upcoming release. I guess in theory it could be useful to other Python implementations like pypy, etc. Some more research is needed to decide on what would be a small set of useful strategy types. Joannah Nanjekye could likely help us since her PhD research was related to this. I chatted a little with her at the core sprint about this.

It would make sense to look what other GC language implementations do and learn from that (e.g. Java, C#). My impression is that options for those are fairly low level and they only have meaning if you are using a specific GC implementation. Having a hundred different knobs that no one knows how to set it not good. Having one knob that doesn’t give enough control is not great either. It will be a bit challenging to find a balance.

---

<div class="post-metadata">

**Author:** ![ncoghlan](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/ncoghlan/32/14266_2.png) [@ncoghlan](https://discuss.python.org/u/ncoghlan)\
**Post date:** [September 30, 2024, 12:58am UTC](https://discuss.python.org/t/add-config-option-to-control-cyclic-garbage-collector-strategy/66125/4 "2024-09-30T00:58:06Z")

</div>

The idea seems similar to the modern trend of operating systems offering high level “performance” vs “power consumption” setting combinations, without having to fiddle with all the individual power management settings.

It’s probably also OK if some of the strategies have no effect on different GC designs relative to their default settings.

On the bikeshed painting front, perhaps the non-default strategies should all start with “min-” to emphasise that they’re minimising usage of a resource?

- “min-memory” (aka “aggressive”): avoids excessive memory use at the expense of potentially increased runtime overhead and potentially long GC pauses
- “min-overhead” (aka “throughput”): avoids excessive runtime overhead at the expense of potentially increased peak and steady state memory usage, and without specifically constraining the duration of any particular GC run
- “min-latency” (aka “latency”): avoids excessive GC pauses at the expense of potentially increased runtime overhead and potentially increased memory usage

The “min-” prefixes would also leave the door open to offering 7 pretuned presets rather than 4 (omit the prefix to split the difference between the minimised settings for that resource and the default balanced settings) if that ever seemed sufficiently useful to be worth doing.

---

<div class="post-metadata">

**Author:** ![nas](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/nas/32/536_2.png) [@nas](https://discuss.python.org/u/nas)\
**Post date:** [September 30, 2024, 4:50am UTC](https://discuss.python.org/t/add-config-option-to-control-cyclic-garbage-collector-strategy/66125/5 "2024-09-30T04:50:30Z")

</div>

Perhaps the word “strategy” is not the best since that implies how it’s done rather than the goal or objective. For power management settings, I’ve seen the word “plan” or “mode”. Some other possible options: bias, preference, pref, priority.

If we use one of those words, I think your “min” prefixes read better. We are not minimizing those things as much as possible. We are biasing the tuning to favour them vs other contradictory objectives. BTW, I don’t like the “aggressive” label but couldn’t think of something better.

---

<div class="post-metadata">

**Author:** ![nanjekyejoannah](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/nanjekyejoannah/32/529_2.png) [@nanjekyejoannah](https://discuss.python.org/u/nanjekyejoannah)\
**Post date:** [September 30, 2024, 7:41am UTC](https://discuss.python.org/t/add-config-option-to-control-cyclic-garbage-collector-strategy/66125/6 "2024-09-30T07:41:57Z")

</div>

TLDR; The short story is I support exposing such a configuration.  
I have written something about the usefulness of threshold tuning  
with a subset of experiments in this paper:  
[https://dl.acm.org/doi/abs/10.5555/3566055.3566071](https://dl.acm.org/doi/abs/10.5555/3566055.3566071)

---

<div class="post-metadata">

**Author:** ![ncoghlan](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/ncoghlan/32/14266_2.png) [@ncoghlan](https://discuss.python.org/u/ncoghlan)\
**Post date:** [September 30, 2024, 8:54am UTC](https://discuss.python.org/t/add-config-option-to-control-cyclic-garbage-collector-strategy/66125/7 "2024-09-30T08:54:14Z")

</div>

> [@nas](#):
>
> If we use one of those words, I think your “min” prefixes read better. We are not minimizing those things as much as possible. We are biasing the tuning to favour them vs other contradictory objectives.

That’s a valid point - while I was reading those names with an inferred “as far as is reasonable” on the end, that inference was based on already knowing what I meant. Maybe `low-memory`/`low-overhead`/`low-latency`?

As far potential option names go, `--gc-preset` or `--gc-tune` might be clearer than “-gc-strategy”.

I suspect the option will be obscure enough that the exact names won’t matter much in practice - anyone motivated enough to go looking for the option in the first place is unlikely to be put off by the finer details.

---

<div class="post-metadata">

**Author:** ![nas](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/nas/32/536_2.png) [@nas](https://discuss.python.org/u/nas)\
**Post date:** [September 30, 2024, 3:02pm UTC](https://discuss.python.org/t/add-config-option-to-control-cyclic-garbage-collector-strategy/66125/8 "2024-09-30T15:02:59Z")

</div>

Oh, I like that. `PYTHON_GC_PRESET=low-memory` reads well to me. And if we need another level, `lower-memory`.
