Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 33.9k
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
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
5e6eda9de12b98035eff31569a53518e3f39995a84f22d0dacf39d57b8402133bf69b04de466e9bb32a6385f298354997f9bbf8a08d1cf35188aed8e0da48346c77677ca8d1ced6c27329e17641a839108631805a0569bb4c3c0f947bfa7edd69ffaba75803eef31948703297d1eddad8a8150c7a37237b2073ac21a522d7b376d4562ee42ed8f5cd6da97b7cf24942fac6af64aa2073f1351682b4ba0424d1de284ae7dbe9de30c51a32ce7104518f7a838918080a10457119923ca7a99c2ae13bc73eec1808ae7b98e590383eaec959db05b34b42837bfe6ebefa35eb7a0801ef4a39771e574b5c43f1bfc39069b25c8be776c31c6bda1f8ab6261ff8de28b28afb30d30300e193794e9f1262a6a6471File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
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 \ | ||
Member 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. MemberAuthor 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 MemberAuthor
| ||
| {\ | ||
| .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.