mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
bpo-45953: Statically allocate the main interpreter (and initial thread state). (gh-29883)
Previously, the main interpreter was allocated on the heap during runtime initialization. Here we instead embed it into _PyRuntimeState, which means it is statically allocated as part of the _PyRuntime global. The same goes for the initial thread state (of each interpreter, including the main one). Consequently there are fewer allocations during runtime/interpreter init, fewer possible failures, and better memory locality. FYI, this also helps efforts to consolidate globals, which in turns helps work on subinterpreter isolation. https://bugs.python.org/issue45953
This commit is contained in:
parent
0bbf30e2b9
commit
ed57b36c32
8 changed files with 115 additions and 34 deletions
|
@ -8,6 +8,8 @@ extern "C" {
|
|||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "pycore_atomic.h" // _Py_atomic_address
|
||||
#include "pycore_ast_state.h" // struct ast_state
|
||||
#include "pycore_context.h" // struct _Py_context_state
|
||||
|
@ -70,13 +72,18 @@ struct atexit_state {
|
|||
|
||||
/* interpreter state */
|
||||
|
||||
// The PyInterpreterState typedef is in Include/pystate.h.
|
||||
/* PyInterpreterState holds the global state for one of the runtime's
|
||||
interpreters. Typically the initial (main) interpreter is the only one.
|
||||
|
||||
The PyInterpreterState typedef is in Include/pystate.h.
|
||||
*/
|
||||
struct _is {
|
||||
|
||||
struct _is *next;
|
||||
|
||||
struct pythreads {
|
||||
uint64_t next_unique_id;
|
||||
/* The linked list of threads, newest first. */
|
||||
struct _ts *head;
|
||||
/* Used in Modules/_threadmodule.c. */
|
||||
long count;
|
||||
|
@ -104,6 +111,9 @@ struct _is {
|
|||
int _initialized;
|
||||
int finalizing;
|
||||
|
||||
/* Was this interpreter statically allocated? */
|
||||
bool _static;
|
||||
|
||||
struct _ceval_state ceval;
|
||||
struct _gc_runtime_state gc;
|
||||
|
||||
|
@ -166,8 +176,26 @@ struct _is {
|
|||
|
||||
struct ast_state ast;
|
||||
struct type_cache type_cache;
|
||||
|
||||
/* The following fields are here to avoid allocation during init.
|
||||
The data is exposed through PyInterpreterState pointer fields.
|
||||
These fields should not be accessed directly outside of init.
|
||||
|
||||
All other PyInterpreterState 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. Also see _PyRuntimeState regarding the various mutex fields.
|
||||
*/
|
||||
|
||||
/* the initial PyInterpreterState.threads.head */
|
||||
struct _ts _initial_thread;
|
||||
};
|
||||
|
||||
|
||||
/* other API */
|
||||
|
||||
extern void _PyInterpreterState_ClearModules(PyInterpreterState *interp);
|
||||
extern void _PyInterpreterState_Clear(PyThreadState *tstate);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue