You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Store current interpreter as a thread local variable #140544
There's a lot of code which accesses the current interpreter state especially under free-threading via PyInterpreterState_Get. Currently to lookup interpreter state first the thread state is accessed then read by ts->interp but it can be optimized to be stored in a thread local variable _Py_tss_current_interp so that it can be read directly.
I am planning to add _Py_tss_current_interp to store the pointer to current interpreter state so that calls like PyInterpreterState_Get are just a fixed offset tls lookup similar to _PyThreadState_GET.
You'd probably be interested in #132312. Thread-local accesses are slow.
Thread-local accesses are slow but what we have currently is even slower because currently first the thread state is read which is thread local then ts->interp which is dependent memory read, by using a dedicated thread local we avoid the dependent memory read.
Do you have benchmarks? You have to take into account that we're going to have to read and write to _Py_tss_current_interp any time we attach or detach a thread state, otherwise we break subinterpreters. I'd expect a single pointer read to be pretty fast compared to extra thread-local reads and writes.
I haven't benchmarked it yet, will do. Attaching and detaching is done primarily before blocking calls which takes much more time so I don't expect the extra tls writes to have meaningful effect.
Do those benchmarks include any code using subinterpreters? I'm mostly concerned about when we're frequently changing the current interpreter.
Not that I know of, fwiw there's far more overhead in switching interpreters than a single tls write would have any effect, it is literally two mov instructions.
Please take a bit more time and don't rush to make these sorts of changes. Speed of thread local storage depends a lot on whether Python is built as a shared library.
Do you mean when python is compiled with --enable-shared?
Yes
Sorry, the benchmarks results were positive hence I merged it, will wait for more time in future.
Thanks. By "these sorts of changes" I meant:
Changes that involve cross-cutting concerns (i.e., that affect multiple modules). PyThreadState and PyInterpreterState accesses happen across the interpreter, which makes modifying them more risky.
Performance changes that are dependent on OS, build configuration, or otherwise difficult to measure. Thread local state falls into this category.
I don't think there's anything actionable to do here and this looks like a nice small speed up.
Activity
corona10 commentedon Oct 24, 2025
Do you mean declaring current_interp with
_Py_thread_local?I think it would be worth running a benchmark to see the effect.
ZeroIntensity commentedon Oct 24, 2025
The (attached) thread state is a thread-local variable; how would adding another one make things any faster?
kumaraditya303 commentedon Oct 24, 2025
I am planning to add
_Py_tss_current_interpto store the pointer to current interpreter state so that calls likePyInterpreterState_Getare just a fixed offset tls lookup similar to_PyThreadState_GET.ZeroIntensity commentedon Oct 24, 2025
You'd probably be interested in #132312. Thread-local accesses are slow.
kumaraditya303 commentedon Oct 24, 2025
Thread-local accesses are slow but what we have currently is even slower because currently first the thread state is read which is thread local then
ts->interpwhich is dependent memory read, by using a dedicated thread local we avoid the dependent memory read.ZeroIntensity commentedon Oct 24, 2025
Do you have benchmarks? You have to take into account that we're going to have to read and write to
_Py_tss_current_interpany time we attach or detach a thread state, otherwise we break subinterpreters. I'd expect a single pointer read to be pretty fast compared to extra thread-local reads and writes.kumaraditya303 commentedon Oct 24, 2025
I haven't benchmarked it yet, will do. Attaching and detaching is done primarily before blocking calls which takes much more time so I don't expect the extra tls writes to have meaningful effect.
gh-140544: cleanup `HAVE_THREAD_LOCAL` checks in pystate.c (#140547)
kumaraditya303 commentedon Oct 25, 2025
Benchmark shows that it is 1% faster on pyperformance with regex upto 9% faster on linux and 3% faster on macos arm64.
ZeroIntensity commentedon Oct 25, 2025
Surprising!
Do those benchmarks include any code using subinterpreters? I'm mostly concerned about when we're frequently changing the current interpreter.
kumaraditya303 commentedon Oct 25, 2025
Not that I know of, fwiw there's far more overhead in switching interpreters than a single tls write would have any effect, it is literally two mov instructions.
ZeroIntensity commentedon Oct 25, 2025
Ok, sounds good. I'll review the PR in the morning.
gh-140544: store pointer to interpreter state as a thread local for f…
1 remaining item
colesbury commentedon Oct 25, 2025
Please take a bit more time and don't rush to make these sorts of changes. Speed of thread local storage depends a lot on whether Python is built as a shared library.
kumaraditya303 commentedon Oct 25, 2025
Sorry, the benchmarks results were positive hence I merged it, will wait for more time in future.
Do you mean when python is compiled with
--enable-shared?cdce8p commentedon Oct 26, 2025
I'm seeing a new error in the mypyc test suite. Left some details in a comment on the PR #140573 (comment).
kumaraditya303 commentedon Oct 26, 2025
Please check if #140623 fixes it
colesbury commentedon Oct 27, 2025
Yes
Thanks. By "these sorts of changes" I meant:
PyThreadStateandPyInterpreterStateaccesses happen across the interpreter, which makes modifying them more risky.I don't think there's anything actionable to do here and this looks like a nice small speed up.
gh-140544: fix build for including `pycore_pystate.h` when `HAVE_THRE…
gh-140544: Always assume that thread locals are available (GH-140690)
pythongh-140544: cleanup `HAVE_THREAD_LOCAL` checks in pystate.c (pyt…
pythongh-140544: store pointer to interpreter state as a thread local…
pythongh-140544: use faster `_PyInterpreterState_GET` for type lock (p…
pythongh-140544: fix build for including `pycore_pystate.h` when `HAV…
pythongh-140544: Always assume that thread locals are available (pyth…