-
-
Notifications
You must be signed in to change notification settings - Fork 32.2k
gh-135944: Add a "Runtime Components" Section to the Execution Model Docs #135945
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
base: main
Are you sure you want to change the base?
gh-135944: Add a "Runtime Components" Section to the Execution Model Docs #135945
Conversation
@@ -398,6 +398,75 @@ See also the description of the :keyword:`try` statement in section :ref:`try` | |||
and :keyword:`raise` statement in section :ref:`raise`. | |||
|
|||
|
|||
.. _execcomponents: | |||
|
|||
Runtime Components |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be a good idea to mention that this is CPython specific. Other implementations are allowed to have different runtime models.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is meant to be implementation agnostic
Oh, oops, didn't see this. Some parts are CPython specific here, though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm trying to avoid any CPython-specific notions here. Do you have an example of another runtime model?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I'm not familiar with how any other implementations work, this is coming solely off a bit of speculation on my part. My concern is that a thread is inherently CPython-specific, because some Python implementations exist in areas that don't have access to OS threads, such as Brython for JS, and probably MicroPython/CircuitPython for some microcontrollers.
I do think that this is a great section to have for subinterpreters, I just think it'd be better to keep some parts of it CPython specific. Does that make sense?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From a conceptual standpoint, which is the level of this text, threads are not implementation-specific (or platform-specific): the Python runtime always deals with at least the one thread in which it was started. Not all platforms and implementations support multiple threads, but that's a different matter. I'll add a sentence clarifying that point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I think I can get behind that. Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the question of implementations that do not have access to OS threads, unless they are unable to create Thread objects, I think this is covered by the possibility of multiple Python threads may be mapped to the single OS thread available. I'm assuming this is multiple Python threads in one interpreter, but interested to be reassured about the multiplicity of the relationships in this data model. I'm reading "OS thread" as "JVM Thread" for my purposes. It's not necessarily the same, but I don't think we can/should peek behind that particular abstraction.
Doc/reference/executionmodel.rst
Outdated
interpreter | ||
Python thread (runs bytecode) | ||
|
||
when a Python program starts, it looks exactly like that, with one |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
capitalization: When
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
Doc/reference/executionmodel.rst
Outdated
If the runtime supports using multiple interpreters then each OS thread | ||
will have at most one Python thread for each interpreter. However, | ||
only one is active in the OS thread at a time. Switching between | ||
interpreters means changing the active Python thread. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably I'm misreading:
If the runtime supports using multiple interpreters then each OS thread | |
will have at most one Python thread for each interpreter. However, | |
only one is active in the OS thread at a time. Switching between | |
interpreters means changing the active Python thread. | |
If the runtime supports using multiple interpreters then each OS thread | |
will have at least one Python thread for each interpreter. However, | |
only one is active in the OS thread at a time. Switching between | |
interpreters in the current OS thread means changing the active Python thread. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's "at most" because there may be zero or one Python thread per thread per interpreter. However, that isn't strictly true, since you can create as many thread states as you want. Only one can be active at a time for a give thread and each one is strictly bound to a single thread. I'll tweak the wording. Thanks for pointing this out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
FWIW, I'm going to open a DPO thread about this addition before merging, to make sure there's sufficient visibility. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very much support the idea of clearly explaining this. I hope the comments are not too ignorant to be useful.
While a program always starts with exactly one of each of those, it may | ||
grow to include multiple of each. Hosts and processes are isolated and | ||
independent from one another. However, threads are not. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This falls a little oddly: "multiples of each". Threads, sure. But to say that a (Python) program could grow to include multiple hosts or processes would take a more extended idea of "program" than I think the execution model seeks to address. Wouldn't it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. I'll narrow that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
The way they share resources is exactly what can make threads a pain: | ||
two threads running at the same arbitrary time on different CPU cores | ||
can accidentally interfere with each other's use of some shared data. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sounds a bit like the risk of accidents is unavoidable. Though I take your point, some science is available, so I offer: "The care needed to co-ordinate access to intentionally shared data, when two or more threads could be running, is exactly what makes threads a painful way to exploit the potential concurrence of multiple CPUs."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Arguably, the risk of accidents with threads is unavoidable. 😄 That said, I'll clarify similarly to what you've suggested.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
Doc/reference/executionmodel.rst
Outdated
It completely encapsulates all of the non-process-global runtime state | ||
that the interpreter's Python threads share. For example, all its | ||
threads share :data:`sys.modules`. Every Python thread belongs to a | ||
single interpreter and runs using that shared state. The initial |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think your point, providing an important example of this encapsulation, is:
all its threads share :data:sys.modules
, but each interpreter will manage its own :data:sys.modules
independently.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
Doc/reference/executionmodel.rst
Outdated
Python thread. Still, regardless of how many are *associated* with | ||
an OS thread, only one Python thread can be actively *running* in | ||
an OS thread at a time. Switching between interpreters means | ||
changing the active Python thread. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"... for that particular OS thread."
Actually, the use of two terms may be why I feel like adding words. If "active" and "running" mean the same thing, I would say choose one. If there is an important distinction, it's not clear. Should we maybe refer to the (one) active Python thread, in each interpreter, for a given OS thread. That may or may not be running as far as the OS is concerned (if that even matters to us).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this is the part where it was hardest to get the wording right. I'll clarify.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree. Looking back, I realise the relevant state of an OS thread is "runnable", rather than "running". We don't care whether the OS thread is actually running, only whether it might make progress "without asking" or is properly blocked. But I struggle to understand how this is in CPython, relates to thread state, and what part of that is implementation-neutral.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed (hopefullly) -- let me know what you think of the updated text
Doc/reference/executionmodel.rst
Outdated
|
||
Every Python thread is associated with a single OS thread, which is | ||
where it runs. However, multiple Python threads can be associated with | ||
the same OS thread. For example, an OS thread might run code with a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We haven't precluded, but haven't expicitly mentioned, one OS thread associated with multiple Python threads in the same interepreter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no prohibition. You're right that it's worth pointing out explicitly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
@@ -398,6 +398,75 @@ See also the description of the :keyword:`try` statement in section :ref:`try` | |||
and :keyword:`raise` statement in section :ref:`raise`. | |||
|
|||
|
|||
.. _execcomponents: | |||
|
|||
Runtime Components |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the question of implementations that do not have access to OS threads, unless they are unable to create Thread objects, I think this is covered by the possibility of multiple Python threads may be mapped to the single OS thread available. I'm assuming this is multiple Python threads in one interpreter, but interested to be reassured about the multiplicity of the relationships in this data model. I'm reading "OS thread" as "JVM Thread" for my purposes. It's not necessarily the same, but I don't think we can/should peek behind that particular abstraction.
@gpshead, I've updated the PR to address your comments at https://discuss.python.org/t/proposal-add-text-to-the-language-reference-about-runtime-components/96922/2, Thanks! |
The section provides a brief overview of the Python runtime's execution environment.
This is meant to be implementation agnostic, If that doesn't hold true then we should take a different approach.
📚 Documentation preview 📚: https://cpython-previews--135945.org.readthedocs.build/