Skip to content
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

Use member non-pointer declarations in Py*State structs instead of heap-allocated pointers. #176

Closed
6 of 41 tasks
ericsnowcurrently opened this issue Dec 13, 2021 · 4 comments
Assignees

Comments

@ericsnowcurrently
Copy link
Collaborator

ericsnowcurrently commented Dec 13, 2021

(See #177.)

The full runtime state of a cpython process is found in PyRuntimeState, PyInterpreterState, and PyThreadState(and, for now, a bunch of static variables), which currently form a single tree at runtime under the_PyRuntime` global variable. Currently these three structs hold many pointers, which are (allocated and) populated during runtime initialization.

For most of the pointers we could instead replace them with static declarations (of the the corresponding data) in the relevant Py*State structs. (This wouldn't work for any variables where the size isn't fixed at compile time (e.g. PyVarObject) but it should work for most.)

Structure

struct pyruntimestate {  # _PyRuntimeState
    struct _Py_global_objects {
        struct {
        } singletons;
        struct {
        } freelists;
    } global_objects;
};

struct _is {  # PyInterpreterState
    struct _Py_global_objects {
        struct {
        } singletons;
        struct {
        } freelists;
        struct {
        } caches;
    } global_objects;
};

TODO

Note that this only covers the current members of _PyRuntimeState, PyInterpreterState, and PyThreadState. Current static globals will be dealt with separately.

  • consolidate global objects
    • singletons
    • free lists
      • move _Py_exc_state.memerrors_freelist to _PyRuntimeState.global_objects.freelists.memory_errors
      • move PyInterpreterState.float_state to PyInterpreterState.global_objects.freelists.float`
      • move PyInterpreterState.tuple_state to PyInterpreterState.global_objects.freelists.tuple`
      • move PyInterpreterState.list_state to PyInterpreterState.global_objects.freelists.list`
      • move PyInterpreterState.dict_state to PyInterpreterState.global_objects.freelists.dict`
      • move PyInterpreterState.async_gen_state to PyInterpreterState.global_objects.freelists.async_gen`
      • move PyInterpreterState.context_state to PyInterpreterState.global_objects.freelists.context`
      • move PyInterpreterState.slice_cache to PyInterpreterState.global_objects.freelists`
      • [ ]
    • caches
      • move PyInterpreterState.type_cache to _PyRuntimeState.global_objects.caches.type_attrs`
      • move _Py_unicode_state.interned into PyInterpreterState.global_objects.caches
  • statically allocate (and initialize) the top-level structures #178
    • _PyRuntimeState.interpreters.main
    • the initial per-interpreter PyThreadState
  • add structure and helpers
    • add _PyRuntimeState.global_objects and helpers
    • add _PyRuntimeState.global_objects.singletons and helpers
    • add _PyRuntimeState.global_objects.freelists and helpers
    • add _PyRuntimeState.global_objects.caches and helpers
    • add helpers for statically allocating/initializing a string
    • add helpers for statically allocating/initializing a dict
    • add helpers for statically allocating/initializing a list
  • statically allocate objects
    • singletons
    • free lists
    • caches
    • state
      • PyInterpreterState.modules (dict)
      • PyInterpreterState.modules_by_index (list)
      • PyInterpreterState.sysdict (dict)
      • PyInterpreterState.builtins (dict)
      • PyInterpreterState.importlib (dict)
      • PyInterpreterState.codec_search_path (list)
      • PyInterpreterState.codec_search_cache (dict)
      • PyInterpreterState.codec_error_registry (dict)
      • PyInterpreterState.dict (dict)
      • PyInterpreterState.warnings.filters (list)
      • PyInterpreterState.warnings.once_registry (dict)
      • PyInterpreterState.gc.trash_delete_later (list)
      • PyInterpreterState.gc.garbage (list)
      • PyInterpreterState.gc.callbacks (list)
      • PyInterpreterState.audit_hooks (list)
      • PyThreadState.dict (dict)
      • PyThreadState.trash_delete_later (list)
  • statically allocate non-object state (?)
@gvanrossum
Copy link
Collaborator

This sounds like an Epic, right? Many of the subtasks are worthy of being separate PRs and hence separate issues, according to our new approach to the Project board.

@ericsnowcurrently
Copy link
Collaborator Author

Correct. I added the "Epic" label.

@ericsnowcurrently
Copy link
Collaborator Author

The changes so far have had almost zero impact on performance. So I'm probably going to table this overall effort. (It's worth doing for other reasons, but not for improving performance.) However, there may be a few specific parts that are worth doing. I'll create separate tasks for any of those.

@ericsnowcurrently
Copy link
Collaborator Author

I'm closing this as it's so low priority at this point that it doesn't need to be on our board.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants