This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Statically allocate interpreter states as much as possible.
Type: Stage: patch review
Components: Interpreter Core Versions: Python 3.11
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: eric.snow Nosy List: Mark.Shannon, brandtbucher, eric.snow, gvanrossum, mdk, miss-islington, vstinner
Priority: normal Keywords: patch

Created on 2021-12-01 18:50 by eric.snow, last changed 2022-04-11 14:59 by admin.

Pull Requests
URL Status Linked Edit
PR 29883 merged eric.snow, 2021-12-01 19:30
PR 30092 merged eric.snow, 2021-12-13 20:44
PR 30096 merged eric.snow, 2021-12-14 01:16
PR 30588 merged eric.snow, 2022-01-13 23:04
PR 30589 merged eric.snow, 2022-01-13 23:36
PR 30590 merged eric.snow, 2022-01-13 23:38
PR 31038 merged eric.snow, 2022-01-31 19:55
Messages (15)
msg407476 - (view) Author: Eric Snow (eric.snow) * (Python committer) Date: 2021-12-01 18:50
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.
msg408507 - (view) Author: Eric Snow (eric.snow) * (Python committer) Date: 2021-12-14 01:04
New changeset 121f1f893a39d0b58d3d2b5597505c154ecaac2a by Eric Snow in branch 'main':
bpo-45953: Statically initialize the small ints. (gh-30092)
https://github.com/python/cpython/commit/121f1f893a39d0b58d3d2b5597505c154ecaac2a
msg410315 - (view) Author: Eric Snow (eric.snow) * (Python committer) Date: 2022-01-11 16:37
New changeset cf496d657a1a82eaf9ebfb47d721676fef6effa5 by Eric Snow in branch 'main':
bpo-45953: Statically allocate and initialize global bytes objects. (gh-30096)
https://github.com/python/cpython/commit/cf496d657a1a82eaf9ebfb47d721676fef6effa5
msg410441 - (view) Author: Eric Snow (eric.snow) * (Python committer) Date: 2022-01-12 23:28
New changeset ed57b36c32e521162dbb97199e64a340d3bff827 by Eric Snow in branch 'main':
bpo-45953: Statically allocate the main interpreter (and initial thread state). (gh-29883)
https://github.com/python/cpython/commit/ed57b36c32e521162dbb97199e64a340d3bff827
msg410536 - (view) Author: Eric Snow (eric.snow) * (Python committer) Date: 2022-01-14 00:09
New changeset 324908ba936d5d262026deebb81f050803848c41 by Eric Snow in branch 'main':
bpo-45953: Statically initialize all the PyThreadState fields we can. (gh-30590)
https://github.com/python/cpython/commit/324908ba936d5d262026deebb81f050803848c41
msg410537 - (view) Author: Eric Snow (eric.snow) * (Python committer) Date: 2022-01-14 00:17
New changeset 322f962f3ee31d0dbde99e36379de8488ccc6804 by Eric Snow in branch 'main':
bpo-45953: Statically initialize all the non-object PyInterpreterState fields we can. (gh-30589)
https://github.com/python/cpython/commit/322f962f3ee31d0dbde99e36379de8488ccc6804
msg412046 - (view) Author: Brandt Bucher (brandtbucher) * (Python committer) Date: 2022-01-29 00:57
Any chance we could revert the recent renaming of tstate.exc_state and tstate.root_cframe in https://github.com/python/cpython/pull/30590? It broke Greenlet again:

https://github.com/python-greenlet/greenlet/issues/288

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.
msg412213 - (view) Author: Eric Snow (eric.snow) * (Python committer) Date: 2022-01-31 17:22
> Any chance we could revert the recent renaming of tstate.exc_state and tstate.root_cframe

Yeah, I'll sort this out.  Sorry for that.
msg412291 - (view) Author: miss-islington (miss-islington) Date: 2022-02-01 17:02
New changeset f78be59c83c151d94902daef56218530c52e29e7 by Eric Snow in branch 'main':
bpo-45953: Preserve backward compatibility on some PyThreadState field names. (GH-31038)
https://github.com/python/cpython/commit/f78be59c83c151d94902daef56218530c52e29e7
msg416159 - (view) Author: Julien Palard (mdk) * (Python committer) Date: 2022-03-28 11:25
Since https://github.com/python/cpython/commit/121f1f893a39d0b58d3d2b5597505c154ecaac2a, `sys.getrefcount(1)` is surprising:

    >>> __import__("sys").getrefcount(1)
    1000000210

Should sys.getrefcount try to "fix" the value like by returning `PyREFCNT(object) % 999999999`? (But using a define to avoid the "magic, copy/pasted value").
msg416161 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2022-03-28 12:16
> 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.
msg416170 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2022-03-28 14:14
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)
msg416208 - (view) Author: Julien Palard (mdk) * (Python committer) Date: 2022-03-28 20:24
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?
msg416210 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2022-03-28 20:56
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?
msg416245 - (view) Author: Julien Palard (mdk) * (Python committer) Date: 2022-03-29 07:04
> 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.
History
Date User Action Args
2022-04-11 14:59:53adminsetgithub: 90111
2022-03-29 07:04:09mdksetmessages: + msg416245
2022-03-28 20:56:13gvanrossumsetmessages: + msg416210
2022-03-28 20:24:27mdksetmessages: + msg416208
2022-03-28 14:14:33gvanrossumsetmessages: + msg416170
2022-03-28 12:16:29vstinnersetmessages: + msg416161
2022-03-28 11:25:23mdksetnosy: + mdk
messages: + msg416159
2022-02-01 17:02:41miss-islingtonsetnosy: + miss-islington
messages: + msg412291
2022-01-31 19:55:00eric.snowsetpull_requests: + pull_request29221
2022-01-31 17:22:16eric.snowsetmessages: + msg412213
2022-01-29 00:57:25brandtbuchersetnosy: + brandtbucher
messages: + msg412046
2022-01-14 01:22:24vstinnersetnosy: + vstinner
2022-01-14 00:17:46eric.snowsetmessages: + msg410537
2022-01-14 00:09:33eric.snowsetmessages: + msg410536
2022-01-13 23:38:17eric.snowsetpull_requests: + pull_request28788
2022-01-13 23:36:15eric.snowsetpull_requests: + pull_request28787
2022-01-13 23:04:42eric.snowsetpull_requests: + pull_request28786
2022-01-12 23:28:55eric.snowsetmessages: + msg410441
2022-01-11 16:37:34eric.snowsetmessages: + msg410315
2021-12-14 01:16:00eric.snowsetpull_requests: + pull_request28319
2021-12-14 01:04:10eric.snowsetmessages: + msg408507
2021-12-13 20:44:00eric.snowsetpull_requests: + pull_request28315
2021-12-01 20:48:09gvanrossumsetnosy: + gvanrossum
2021-12-01 19:30:34eric.snowsetkeywords: + patch
stage: needs patch -> patch review
pull_requests: + pull_request28109
2021-12-01 18:50:39eric.snowcreate