-
-
Notifications
You must be signed in to change notification settings - Fork 32.2k
bpo-45953: Statically allocate the main interpreter (and initial thread state). #29883
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
Changes from all commits
5e6eda9
de12b98
035eff3
1569a53
518e3f3
9995a84
f22d0da
cf39d57
b840213
3bf69b0
4de466e
9bb32a6
385f298
354997f
9bbf8a0
8d1cf35
188aed8
e0da483
46c7767
7ca8d1c
ed6c273
29e1764
1a83910
8631805
a0569bb
4c3c0f9
47bfa7e
dd69ffa
ba75803
eef3194
8703297
d1eddad
8a8150c
7a37237
b2073ac
21a522d
7b376d4
562ee42
ed8f5cd
6da97b7
cf24942
fac6af6
4aa2073
f135168
2b4ba04
24d1de2
84ae7db
e9de30c
51a32ce
7104518
f7a8389
18080a1
0457119
923ca7a
99c2ae1
3bc73ee
c1808ae
7b98e59
0383eae
c959db0
5b34b42
837bfe6
ebefa35
eb7a080
1ef4a39
771e574
b5c43f1
bfc3906
9b25c8b
e776c31
c6bda1f
8ab6261
ff8de28
b28afb3
0d30300
e193794
e9f1262
a6a6471
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,8 +11,10 @@ extern "C" { | |
#include "pycore_atomic.h" /* _Py_atomic_address */ | ||
#include "pycore_gil.h" // struct _gil_runtime_state | ||
#include "pycore_global_objects.h" // struct _Py_global_objects | ||
#include "pycore_interp.h" // struct _is | ||
#include "pycore_unicodeobject.h" // struct _Py_unicode_runtime_ids | ||
|
||
|
||
/* ceval state */ | ||
|
||
struct _ceval_runtime_state { | ||
|
@@ -53,6 +55,9 @@ typedef struct _Py_AuditHookEntry { | |
|
||
/* Full Python runtime state */ | ||
|
||
/* _PyRuntimeState holds the global state for the CPython runtime. | ||
That data is exposed in the internal API as a static variable (_PyRuntime). | ||
*/ | ||
typedef struct pyruntimestate { | ||
/* Has been initialized to a safe state. | ||
|
||
|
@@ -81,7 +86,11 @@ typedef struct pyruntimestate { | |
|
||
struct pyinterpreters { | ||
PyThread_type_lock mutex; | ||
/* The linked list of interpreters, newest first. */ | ||
PyInterpreterState *head; | ||
/* The runtime's initial interpreter, which has a special role | ||
in the operation of the runtime. It is also often the only | ||
interpreter. */ | ||
PyInterpreterState *main; | ||
/* _next_interp_id is an auto-numbered sequence of small | ||
integers. It gets initialized in _PyInterpreterState_Init(), | ||
|
@@ -118,25 +127,44 @@ typedef struct pyruntimestate { | |
|
||
struct _Py_unicode_runtime_ids unicode_ids; | ||
|
||
/* All the objects that are shared by the runtime's interpreters. */ | ||
struct _Py_global_objects global_objects; | ||
// If anything gets added after global_objects then | ||
// _PyRuntimeState_reset() needs to get updated to clear it. | ||
|
||
/* The following fields are here to avoid allocation during init. | ||
The data is exposed through _PyRuntimeState pointer fields. | ||
These fields should not be accessed directly outside of init. | ||
|
||
All other _PyRuntimeState pointer fields are populated when | ||
needed and default to NULL. | ||
|
||
For now there are some exceptions to that rule, which require | ||
allocation during init. These will be addressed on a case-by-case | ||
basis. Most notably, we don't pre-allocated the several mutex | ||
(PyThread_type_lock) fields, because on Windows we only ever get | ||
a pointer type. | ||
*/ | ||
|
||
/* PyInterpreterState.interpreters.main */ | ||
PyInterpreterState _main_interpreter; | ||
} _PyRuntimeState; | ||
|
||
#define _PyThreadState_INIT \ | ||
{ \ | ||
._static = 1, \ | ||
} | ||
#define _PyInterpreterState_INIT \ | ||
{ \ | ||
._static = 1, \ | ||
._initial_thread = _PyThreadState_INIT, \ | ||
} | ||
#define _PyRuntimeState_INIT \ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might as well remove this as well. It is also only used once. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually,
This comment was marked as off-topic.
Sorry, something went wrong. |
||
{ \ | ||
.global_objects = _Py_global_objects_INIT, \ | ||
._main_interpreter = _PyInterpreterState_INIT, \ | ||
} | ||
/* Note: _PyRuntimeState_INIT sets other fields to 0/NULL */ | ||
|
||
static inline void | ||
_PyRuntimeState_reset(_PyRuntimeState *runtime) | ||
{ | ||
/* Make it match _PyRuntimeState_INIT. */ | ||
memset(runtime, 0, (size_t)&runtime->global_objects - (size_t)runtime); | ||
_Py_global_objects_reset(&runtime->global_objects); | ||
} | ||
|
||
/* other API */ | ||
|
||
PyAPI_DATA(_PyRuntimeState) _PyRuntime; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
The main interpreter in _PyRuntimeState.interpreters is now statically | ||
allocated (as part of _PyRuntime). Likewise for the initial thread state of | ||
each interpreter. This means less allocation during runtime init, as well | ||
as better memory locality for these key state objects. |
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.
Can it be turned into a variant below?
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.
Thanks for the tip. What's the advantage?
Uh oh!
There was an error while loading. Please reload this page.
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.
Actually, this is a minor adjustment done while it does not require a separate pull request.
More compact declaration is easier to grasp in a single eye swipe. Like _PyThreadState_INIT is the preallocated's initialized set to one versus _PyThreadState_INIT is... the preallocated's initialized set to one... ah, that's it. In isolation of few lines it sounds funny but when a programmer reads the whole file to assemble a picture what pystate is and what it is capable of, they read in zigzags only.