From 11fdaeed306c9846492a0c80c8062027a27dd168 Mon Sep 17 00:00:00 2001 From: Neil Schemenauer Date: Sat, 28 Sep 2024 20:02:05 -0700 Subject: [PATCH 1/2] Add the `PYTHON_GC_THRESHOLD` environment variable. --- Doc/using/cmdline.rst | 10 ++++++++++ ...-09-28-20-01-40.gh-issue-124742.7kJx88.rst | 4 ++++ Python/gc.c | 19 +++++++++++++++++++ Python/gc_free_threading.c | 19 +++++++++++++++++++ Python/initconfig.c | 2 ++ 5 files changed, 54 insertions(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2024-09-28-20-01-40.gh-issue-124742.7kJx88.rst diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index 6cf42b27718022..2157d543fb45ac 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -976,6 +976,16 @@ conflict. .. versionadded:: 3.4 +.. envvar:: PYTHON_GC_THRESHOLD + + Set the `threshold0` value for the garbage collector. This is the same + as calling `gc.set_threshold(n)` where `n` is value of the variable. Using + an empty value or the value "default" will cause the default threshold to be + used. + + .. versionadded:: 3.13 + + .. envvar:: PYTHONMALLOC Set the Python memory allocators and/or install debug hooks. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-09-28-20-01-40.gh-issue-124742.7kJx88.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-09-28-20-01-40.gh-issue-124742.7kJx88.rst new file mode 100644 index 00000000000000..919bd6bab60989 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2024-09-28-20-01-40.gh-issue-124742.7kJx88.rst @@ -0,0 +1,4 @@ +Add the `PYTHON_GC_THRESHOLD` environment variable. This can be used to set +the `threshold0` value for the garbage collector, similar to calling +`gc.set_threshold()`. If the value is empty or "default", the default +threshold value is used. diff --git a/Python/gc.c b/Python/gc.c index 028657eb8999c1..c3ad64c38c51f7 100644 --- a/Python/gc.c +++ b/Python/gc.c @@ -166,12 +166,31 @@ _PyGC_InitState(GCState *gcstate) #undef INIT_HEAD } +static void +gc_set_threshold_from_env(PyInterpreterState *interp) +{ + const PyConfig *config = _PyInterpreterState_GetConfig(interp); + const char *env = _Py_GetEnv(config->use_environment, + "PYTHON_GC_THRESHOLD"); + if (env == NULL || strcmp(env, "default") == 0) { + return; + } + int threshold = -1; + if (_Py_str_to_int(env, &threshold) < 0) { + return; // parse failed, silently ignore + } + if (threshold > 0) { + interp->gc.young.threshold = threshold; + } +} PyStatus _PyGC_Init(PyInterpreterState *interp) { GCState *gcstate = &interp->gc; + gc_set_threshold_from_env(interp); + gcstate->garbage = PyList_New(0); if (gcstate->garbage == NULL) { return _PyStatus_NO_MEMORY(); diff --git a/Python/gc_free_threading.c b/Python/gc_free_threading.c index a5bc9b9b5782b2..7e5e3f30ef0a10 100644 --- a/Python/gc_free_threading.c +++ b/Python/gc_free_threading.c @@ -838,12 +838,31 @@ _PyGC_InitState(GCState *gcstate) gcstate->young.threshold = 2000; } +static void +gc_set_threshold_from_env(PyInterpreterState *interp) +{ + const PyConfig *config = _PyInterpreterState_GetConfig(interp); + const char *env = _Py_GetEnv(config->use_environment, + "PYTHON_GC_THRESHOLD"); + if (env == NULL || strcmp(env, "default") == 0) { + return; + } + int threshold = -1; + if (_Py_str_to_int(env, &threshold) < 0) { + return; // parse failed, silently ignore + } + if (threshold > 0) { + interp->gc.young.threshold = threshold; + } +} PyStatus _PyGC_Init(PyInterpreterState *interp) { GCState *gcstate = &interp->gc; + gc_set_threshold_from_env(interp); + gcstate->garbage = PyList_New(0); if (gcstate->garbage == NULL) { return _PyStatus_NO_MEMORY(); diff --git a/Python/initconfig.c b/Python/initconfig.c index 58ac5e7d7eaeff..48c8da820bc596 100644 --- a/Python/initconfig.c +++ b/Python/initconfig.c @@ -342,6 +342,8 @@ static const char usage_envvars[] = " on Python memory allocators. Use PYTHONMALLOC=debug to\n" " install debug hooks.\n" "PYTHONMALLOCSTATS: print memory allocator statistics\n" +"PYTHON_GC_THRESHOLD: set threshold0 for the garbage collector. This\n" +" threshold can also be set by gc.set_threshold().\n" "PYTHONCOERCECLOCALE: if this variable is set to 0, it disables the locale\n" " coercion behavior. Use PYTHONCOERCECLOCALE=warn to request\n" " display of locale coercion and locale compatibility warnings\n" From 40be46263ebc0e1511ff3b3bd720e45c3445cf76 Mon Sep 17 00:00:00 2001 From: Neil Schemenauer Date: Sat, 28 Sep 2024 21:03:37 -0700 Subject: [PATCH 2/2] Repair doc markup. --- Doc/using/cmdline.rst | 8 ++++---- .../2024-09-28-20-01-40.gh-issue-124742.7kJx88.rst | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index 2157d543fb45ac..b627ad9704fee0 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -978,10 +978,10 @@ conflict. .. envvar:: PYTHON_GC_THRESHOLD - Set the `threshold0` value for the garbage collector. This is the same - as calling `gc.set_threshold(n)` where `n` is value of the variable. Using - an empty value or the value "default" will cause the default threshold to be - used. + Set the ``threshold0`` value for the garbage collector. This is the same as + calling ``gc.set_threshold(n)`` where ``n`` is value of the variable. Using + an empty value or the value ``default`` will cause the default threshold to + be used. .. versionadded:: 3.13 diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-09-28-20-01-40.gh-issue-124742.7kJx88.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-09-28-20-01-40.gh-issue-124742.7kJx88.rst index 919bd6bab60989..bb52170b043827 100644 --- a/Misc/NEWS.d/next/Core_and_Builtins/2024-09-28-20-01-40.gh-issue-124742.7kJx88.rst +++ b/Misc/NEWS.d/next/Core_and_Builtins/2024-09-28-20-01-40.gh-issue-124742.7kJx88.rst @@ -1,4 +1,4 @@ -Add the `PYTHON_GC_THRESHOLD` environment variable. This can be used to set -the `threshold0` value for the garbage collector, similar to calling -`gc.set_threshold()`. If the value is empty or "default", the default +Add the :envvar:`PYTHON_GC_THRESHOLD` environment variable. This can be used +to set the ``threshold0`` value for the garbage collector, similar to calling +``gc.set_threshold()``. If the value is empty or ``default``, the default threshold value is used.