gh-140544: store pointer to interpreter state as a thread local for fast access (#140573)

This commit is contained in:
Kumar Aditya 2025-10-25 19:56:07 +05:30 committed by GitHub
parent 4ad599501f
commit ef4665f918
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 22 additions and 8 deletions

View file

@ -17,15 +17,16 @@ extern "C" {
static inline struct _Py_freelists *
_Py_freelists_GET(void)
{
PyThreadState *tstate = _PyThreadState_GET();
#ifdef Py_DEBUG
_Py_EnsureTstateNotNULL(tstate);
_Py_AssertHoldsTstate();
#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
}

View file

@ -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(Py_BUILD_CORE_MODULE)
return _Py_tss_interp;
#else
return _PyThreadState_GET()->interp;
#endif
}

View file

@ -0,0 +1 @@
Speed up accessing interpreter state by caching it in a thread local variable. Patch by Kumar Aditya.

View file

@ -78,6 +78,10 @@ _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,
and is same as tstate->interp. */
_Py_thread_local PyInterpreterState *_Py_tss_interp = NULL;
static inline PyThreadState *
current_fast_get(void)
{
@ -89,12 +93,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) \
@ -1281,9 +1288,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");
}

View file

@ -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

Can't render this file because it has a wrong number of fields in line 4.