-
-
Notifications
You must be signed in to change notification settings - Fork 31.7k
[subinterpreter] Make type version tag counter threadsafe for per interpreter GIL #95795
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Good catch. I missed this in gh-94673. |
Oh, I misread that as We should definitely fix |
FTR, the comment in the embedded code snippet above refers to gh-86911. |
@markshannon, what are your thoughts? |
As for me...
Yeah, it would depend on the specialization semantics. Also, the reference to static types in the snippet you pasted above implies a special relationship with those objects that we may need to revisit. For static types (especially builtin ones) we don't expect them to change after (This does imply that we may need to make
Yeah, this may make sense. Ideally we could make this per-interpreter but using an atomic seems like a reasonable alternative. |
What I would prefer, is for immutable, sharable classes to set their tag during initialization, or even statically. We will want the most common types to have pre-defined tags, for rapidly getting type information from version numbers in the higher tier optimizers. |
Currently there are under 100 |
So we would do the following:
At that point we could drop There are a few other things to consider:
That last one would require some extra work, e.g. special-casing non-heap types to use |
That sounds about right. I'm not familiar with all the static initialization logic, but as long the following assertions always hold, I'm happy:
I'd give the two
More asserts is good.
Whether they are static should irrelevant. But if the are immutable and can be shared, then they must have their |
Core static types will continue to use the global value. All other types will use the per-interpreter value. They all share the same range, where the global types use values < 2^16 and each interpreter uses values higher than that.
* main: pythongh-103801: Tools/wasm linting and formatting (python#103796) pythongh-103673: Add missing ForkingUnixStreamServer and ForkingUnixDatagramServer socketservers (python#103674) pythongh-95795: Move types.next_version_tag to PyInterpreterState (pythongh-102343)
The
next_version_tag
intypeobject.c
is currently not thread safe and relies on GIL to protect against concurrent increments across threads.cpython/Objects/typeobject.c
Lines 46 to 50 in 63140b4
For per-interpreter GIL, it must be made thread-safe otherwise the type cache will be affected by race conditions. Static types are not affected because they are immutable so this is a issue for pure Python classes aka heap types. This issue is for discussion of possible implementations.
Possible Solutions:
next_version_tag
counter per interpreter, while this may seems to fix the issue but since objects are shared across the interpreters and the type version tag is also used to represent a current state of a type in the specializing interpreter, two interpreters can have same the same tag for different types this won't work as expected.next_version_tag
an atomic counter and increment it atomically using thepyatomic APIs
. This is my preferred solution sincenext_version_tag
is only modified when a type is modified so is a rare operation and not a performance issue. Since this is just a counterrelaxed ordering
can be used here.cc @ericsnowcurrently
Linked PRs
The text was updated successfully, but these errors were encountered: