From 0ee4abacedb1a68d0b8b5c64951b9cc88ade7f14 Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Fri, 24 Oct 2025 20:03:12 +0530 Subject: [PATCH 1/9] use tls for interp --- Include/internal/pycore_pystate.h | 9 +++++++-- Python/pystate.c | 6 ++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h index ea3dfbd2eef9c1..82cec0081d6fec 100644 --- a/Include/internal/pycore_pystate.h +++ b/Include/internal/pycore_pystate.h @@ -91,6 +91,7 @@ _Py_ThreadCanHandleSignals(PyInterpreterState *interp) #if defined(HAVE_THREAD_LOCAL) && !defined(Py_BUILD_CORE_MODULE) extern _Py_thread_local PyThreadState *_Py_tss_tstate; +extern _Py_thread_local PyInterpreterState *_Py_tss_interp; #endif #ifndef NDEBUG @@ -204,11 +205,15 @@ _Py_EnsureFuncTstateNotNULL(const char *func, PyThreadState *tstate) See also PyInterpreterState_Get() and _PyGILState_GetInterpreterStateUnsafe(). */ static inline PyInterpreterState* _PyInterpreterState_GET(void) { - PyThreadState *tstate = _PyThreadState_GET(); #ifdef Py_DEBUG + PyThreadState *tstate = _PyThreadState_GET(); _Py_EnsureTstateNotNULL(tstate); #endif - return tstate->interp; +#if defined(HAVE_THREAD_LOCAL) && !defined(Py_BUILD_CORE_MODULE) + return _Py_tss_interp; +#else + return PyInterpreterState_Get(); +#endif } diff --git a/Python/pystate.c b/Python/pystate.c index 2f76adf5026012..cc107ed7a5a84c 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -78,6 +78,9 @@ _Py_thread_local PyThreadState *_Py_tss_tstate = NULL; also known as a "gilstate." */ _Py_thread_local PyThreadState *_Py_tss_gilstate = NULL; +/* The interpreter of the attached thread state */ +_Py_thread_local PyInterpreterState *_Py_tss_interp = NULL; + static inline PyThreadState * current_fast_get(void) { @@ -89,12 +92,15 @@ current_fast_set(_PyRuntimeState *Py_UNUSED(runtime), PyThreadState *tstate) { assert(tstate != NULL); _Py_tss_tstate = tstate; + assert(tstate->interp != NULL); + _Py_tss_interp = tstate->interp; } static inline void current_fast_clear(_PyRuntimeState *Py_UNUSED(runtime)) { _Py_tss_tstate = NULL; + _Py_tss_interp = NULL; } #define tstate_verify_not_active(tstate) \ From 04318d007ab23bd208cdbdcae37ae435e9b097d4 Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Fri, 24 Oct 2025 20:31:37 +0530 Subject: [PATCH 2/9] use fast access for freelist --- Include/internal/pycore_freelist.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Include/internal/pycore_freelist.h b/Include/internal/pycore_freelist.h index f3c9a669ad3512..52618a96d4a5df 100644 --- a/Include/internal/pycore_freelist.h +++ b/Include/internal/pycore_freelist.h @@ -17,15 +17,12 @@ extern "C" { static inline struct _Py_freelists * _Py_freelists_GET(void) { - PyThreadState *tstate = _PyThreadState_GET(); -#ifdef Py_DEBUG - _Py_EnsureTstateNotNULL(tstate); -#endif - #ifdef Py_GIL_DISABLED + PyThreadState *tstate = _PyThreadState_GET(); return &((_PyThreadStateImpl*)tstate)->freelists; #else - return &tstate->interp->object_state.freelists; + PyInterpreterState *interp = _PyInterpreterState_GET(); + return &interp->object_state.freelists; #endif } From 7115c75cb40239f68c888a42eade2cac3afa56f5 Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Sat, 25 Oct 2025 08:53:06 +0530 Subject: [PATCH 3/9] cleanup 1 --- Include/internal/pycore_pystate.h | 2 +- Python/pystate.c | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h index 82cec0081d6fec..b35fdf50ccc84b 100644 --- a/Include/internal/pycore_pystate.h +++ b/Include/internal/pycore_pystate.h @@ -212,7 +212,7 @@ static inline PyInterpreterState* _PyInterpreterState_GET(void) { #if defined(HAVE_THREAD_LOCAL) && !defined(Py_BUILD_CORE_MODULE) return _Py_tss_interp; #else - return PyInterpreterState_Get(); + return _PyThreadState_GET()->interp; #endif } diff --git a/Python/pystate.c b/Python/pystate.c index cc107ed7a5a84c..7f03151916a0aa 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1287,9 +1287,8 @@ _PyInterpreterState_RequireIDRef(PyInterpreterState *interp, int required) PyInterpreterState* PyInterpreterState_Get(void) { - PyThreadState *tstate = current_fast_get(); - _Py_EnsureTstateNotNULL(tstate); - PyInterpreterState *interp = tstate->interp; + _Py_AssertHoldsTstate(); + PyInterpreterState *interp = _Py_tss_interp; if (interp == NULL) { Py_FatalError("no current interpreter"); } From c6a7f91322205b62f8d484c4cb047a0b2f26f5a4 Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Sat, 25 Oct 2025 10:31:49 +0530 Subject: [PATCH 4/9] add back assertion --- Include/internal/pycore_freelist.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Include/internal/pycore_freelist.h b/Include/internal/pycore_freelist.h index 52618a96d4a5df..2eaa5f716460dc 100644 --- a/Include/internal/pycore_freelist.h +++ b/Include/internal/pycore_freelist.h @@ -17,6 +17,11 @@ extern "C" { static inline struct _Py_freelists * _Py_freelists_GET(void) { +#ifdef Py_DEBUG + PyThreadState *tstate = _PyThreadState_GET(); + _Py_EnsureTstateNotNULL(tstate); +#endif + #ifdef Py_GIL_DISABLED PyThreadState *tstate = _PyThreadState_GET(); return &((_PyThreadStateImpl*)tstate)->freelists; From 40407f7955f4383e99bd3e0645a715f0fa09c995 Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Sat, 25 Oct 2025 11:45:27 +0530 Subject: [PATCH 5/9] fix build --- Include/internal/pycore_freelist.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Include/internal/pycore_freelist.h b/Include/internal/pycore_freelist.h index 2eaa5f716460dc..3a41ec4b54bb06 100644 --- a/Include/internal/pycore_freelist.h +++ b/Include/internal/pycore_freelist.h @@ -18,8 +18,7 @@ static inline struct _Py_freelists * _Py_freelists_GET(void) { #ifdef Py_DEBUG - PyThreadState *tstate = _PyThreadState_GET(); - _Py_EnsureTstateNotNULL(tstate); + _Py_AssertHoldsTstate(); #endif #ifdef Py_GIL_DISABLED From a42e9738de3572cc315e846fa3da17694a0263a9 Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Sat, 25 Oct 2025 12:23:40 +0530 Subject: [PATCH 6/9] fix globals check --- Tools/c-analyzer/cpython/ignored.tsv | 1 + 1 file changed, 1 insertion(+) diff --git a/Tools/c-analyzer/cpython/ignored.tsv b/Tools/c-analyzer/cpython/ignored.tsv index c3b13d69f0de8e..8b73189fb07dc5 100644 --- a/Tools/c-analyzer/cpython/ignored.tsv +++ b/Tools/c-analyzer/cpython/ignored.tsv @@ -194,6 +194,7 @@ Python/pyfpe.c - PyFPE_counter - Python/import.c - pkgcontext - Python/pystate.c - _Py_tss_tstate - Python/pystate.c - _Py_tss_gilstate - +Python/pystate.c - _Py_tss_interp - ##----------------------- ## should be const From a2b1487e6e5ad26038af8a2fd0bb4ea50f4df6a8 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Sat, 25 Oct 2025 07:26:01 +0000 Subject: [PATCH 7/9] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2025-10-25-07-25-52.gh-issue-140544.lwjtQe.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-10-25-07-25-52.gh-issue-140544.lwjtQe.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-10-25-07-25-52.gh-issue-140544.lwjtQe.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-10-25-07-25-52.gh-issue-140544.lwjtQe.rst new file mode 100644 index 00000000000000..51d2b229ee5b80 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-10-25-07-25-52.gh-issue-140544.lwjtQe.rst @@ -0,0 +1 @@ +Speed up accessing interpreter state by caching it in a thread local variable. Patch by Kumar Aditya. From 2b3d15a785b40fa7427b40dcaa2792fd4f227e45 Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Sat, 25 Oct 2025 19:26:06 +0530 Subject: [PATCH 8/9] review --- Include/internal/pycore_pystate.h | 2 +- Python/pystate.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h index b35fdf50ccc84b..503cddc73fc464 100644 --- a/Include/internal/pycore_pystate.h +++ b/Include/internal/pycore_pystate.h @@ -209,7 +209,7 @@ static inline PyInterpreterState* _PyInterpreterState_GET(void) { PyThreadState *tstate = _PyThreadState_GET(); _Py_EnsureTstateNotNULL(tstate); #endif -#if defined(HAVE_THREAD_LOCAL) && !defined(Py_BUILD_CORE_MODULE) +#if !defined(Py_BUILD_CORE_MODULE) return _Py_tss_interp; #else return _PyThreadState_GET()->interp; diff --git a/Python/pystate.c b/Python/pystate.c index 7f03151916a0aa..f8801b3db063dc 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -78,7 +78,7 @@ _Py_thread_local PyThreadState *_Py_tss_tstate = NULL; also known as a "gilstate." */ _Py_thread_local PyThreadState *_Py_tss_gilstate = NULL; -/* The interpreter of the attached thread state */ +/* The interpreter of the attached thread state. */ _Py_thread_local PyInterpreterState *_Py_tss_interp = NULL; static inline PyThreadState * From 2dc93d3a07cdd701cac8ca36eafe56e73d14480a Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Sat, 25 Oct 2025 19:27:30 +0530 Subject: [PATCH 9/9] improve comment --- Python/pystate.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Python/pystate.c b/Python/pystate.c index f8801b3db063dc..5d0927c6c08196 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -78,7 +78,8 @@ _Py_thread_local PyThreadState *_Py_tss_tstate = NULL; also known as a "gilstate." */ _Py_thread_local PyThreadState *_Py_tss_gilstate = NULL; -/* The interpreter of the attached thread state. */ +/* The interpreter of the attached thread state, + and is same as tstate->interp. */ _Py_thread_local PyInterpreterState *_Py_tss_interp = NULL; static inline PyThreadState *