Repository navigation
Statically allocate interpreter states as much as possible. #90111
Description
Activity
Currently we allocate each new PyInterpreterState in PyInterpreterState_New(). Furthermore, PyInterpreterState is full of pointers which are almost all allocated on the heap during runtime init. We can statically allocate (and initialize?) most of what goes into PyInterpreterState, as well as the main interpreter itself (as part of _PyRuntimeState). This includes each interpreter's initial PyThreadState.
TODO:
- add
PyInterpreterState main;to _PyRuntimeState.interpreters and use it - change references from the pointer to the value
- add
PyThreadState _main;to PyInterpreterState.threads and use it - change references from the pointer to the value
- change PyInterpreterState pointer fields to values (as much as possible)
- change PyThreadState pointer fields to values (as much as possible)
benefits:
- fewer possible failures (no memory) during runtime/interpreter/thread init
- improved memory locality for pointers looked up relative to interpreter/thread state
There is one non-trivial bit: embedding the various PyObject values in PyInterpreterState and PyThreadState means hard-coding the various pieces of the object there (e.g. for dict, its keys/values; for list, its array), as well as adding necessary init code to PyInterpreterState_New() and PyThreadState_New(). The resulting added complexity can be mitigated somewhat with macros or even code generation. (In fact, there is probably significant overlap with Guido's deepfreeze tool.) Regardless, we'll probably need to factor out init funcs for a number of object types, where currently there are only "Py*_New()" funcs that combine allocation and init.
- add
- addedinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)3.11only security fixesonly security fixes
on Dec 1, 2021 - addedinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)
on Dec 1, 2021 ericsnowcurrently commented
on Dec 14, 2021 MemberAuthorMore actionsericsnowcurrently commented
on Jan 11, 2022 MemberAuthorMore actionsericsnowcurrently commented
on Jan 12, 2022 MemberAuthorMore actionsericsnowcurrently commented
on Jan 14, 2022 MemberAuthorMore actionsericsnowcurrently commented
on Jan 14, 2022 MemberAuthorMore actionsAny chance we could revert the recent renaming of tstate.exc_state and tstate.root_cframe in #30590? It broke Greenlet again:
If it's only a name change (and the members themselves are the same), I think reverting it is preferable to burying Greenlet in more compatibility macros and bugging them to put out another new release.
ericsnowcurrently commented
on Jan 31, 2022 MemberAuthorMore actionsAny chance we could revert the recent renaming of tstate.exc_state and tstate.root_cframe
Yeah, I'll sort this out. Sorry for that.
Since 121f1f8,
sys.getrefcount(1)is surprising:>>> __import__("sys").getrefcount(1) 1000000210Should sys.getrefcount try to "fix" the value like by returning
PyREFCNT(object) % 999999999? (But using a define to avoid the "magic, copy/pasted value").Should sys.getrefcount try to "fix" the value (...)
https://peps.python.org/pep-0683/ would make it possible. Right now, I don't think that it's possible.
Right now, a refcount of 1000000210 can be a real value, or it can be an immortal object.
Please don’t try to “fix” anything. The value is only useful if you
understand the implementation. It should map straightforwardly to what’s in
memory.On Mon, Mar 28, 2022 at 05:16 STINNER Victor <report@bugs.python.org> wrote:
STINNER Victor <vstinner@python.org> added the comment:
> Should sys.getrefcount try to "fix" the value (...)
https://peps.python.org/pep-0683/ would make it possible. Right now, I
don't think that it's possible.Right now, a refcount of 1000000210 can be a real value, or it can be an
immortal object.----------
Python tracker <report@bugs.python.org>
<https://bugs.python.org/issue45953\>
--
--Guido (mobile)Hum, and why 999999999? I am probably missing something obvious but 1 should be enough to ensure the value never hits 0. Except for refcount bugs obviously, but I don't think this is the right reason?
I used 999999999 in deepfreeze.py to signify "immortal object". It has been copied by others (small integers are essentially immortal too). I wasn't too sure that the refcount wouldn't go below zero if the interpreter is repeatedly finalized and reinitialized. Once we have official immortal objects (see PEP-683) we should switch to that.
Since you seem to be challenging the value of 999999999, my question to you is, why do you care what the refcount of 1 is?
Since you seem to be challenging the value of 999999999, my question to you is, why do you care what the refcount of 1 is?
Yesterday I was teaching Python, and we were speaking of integer immutability, names being "labels to objects" and so on, and I was showing the memory layout of all of this by hand on a whiteboard while "prooving" my drawings using an interpreter.
While doing so came a question like "So, many modules can use the object int(1)?" So I answered yes, told that I expected many reuse of 1, and went importing sys.getrefcount to show them.
And boom, it printed 1000000209 so I bugged for a few seconds, the value was obviously not the real refcount, and was also obviously bumped by a constant like 100000000, so I went inspecting why and found this commit.
I have nothing against keeping 999999999, but in the other hand it could surprise other people, maybe we should at least document it near sys.getrefcount.
This looks completed, @ericsnowcurrently can this be closed now?
We should add a note in the docs, as @JulienPalard recommended. Arguably, that should be part of #98154.
Otherwise, I'll take a look soon to see if there's anything else left to do.
- added a commit that references this issue
on Dec 16, 2022 Following @JulienPalard comments, I also faced the same issue during a Python course. Whatever is the meaning of refcount, the documentation of
sys.getrefcountshould be fixed. The doc currently says thatReturn the reference count of object. The count returned is generally one higher than you might expect, because it includes the (temporary) reference as an argument to getrefcount().For immortal objects, it is no more the case, the returned number is not the reference count.
Reacted by Eric Snowericsnowcurrently commented
on May 24, 2023 MemberAuthorMore actionsSee gh-98154.
Closing as the docs were updated for immortal objects https://docs.python.org/3.14/library/sys.html#sys.getrefcount
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
Linked PRs