Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

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. #79

Closed
ericsnowcurrently opened this issue Jul 29, 2021 · 6 comments

Comments

@ericsnowcurrently
Copy link
Collaborator

ericsnowcurrently commented Jul 29, 2021

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.)

Benefits

@dpgeorge
Copy link

As a passing comment: a large majority of MicroPython's data structures are statically defined, and even const so they can be put directly in the text section (and usually that is physical ROM). This helps immensely with both fast start up time and minimal RAM usage.

@ericsnowcurrently ericsnowcurrently self-assigned this Aug 2, 2021
@ericsnowcurrently ericsnowcurrently changed the title Use static declarations in Py*State structs instead of heap-allocated pointers. Use member non-pointer declarations in Py*State structs instead of heap-allocated pointers. Aug 9, 2021
@ericsnowcurrently

This comment has been minimized.

@ericsnowcurrently
Copy link
Collaborator Author

Related: python/cpython#29274

@ericsnowcurrently
Copy link
Collaborator Author

@markshannon, I'd like your thoughts on the approach I'm considering for this. It also ties into the discussions we've had on how to deal with all our static variables.

You can see the change for my branch here:

python/cpython@main...ericsnowcurrently:per-interpreter-globals

There are several things that I've tried out:

  • pre-allocate the main interpreter (_PyRuntimeState.main)
  • pre-allocate the initial thread state for each PyInterpreterState
  • move the small ints back to PyInterpreterState (but subinterpreters share with the main interpreter for now)
  • pre-allocate PyInterpreterState.modules (a dict)
  • pre-allocate PyInterpreterState.modules_by_index (a list)

For most of those, each maps to a single commit, so it may be useful to look at the commits separately.

@ericsnowcurrently
Copy link
Collaborator Author

@ericsnowcurrently
Copy link
Collaborator Author

FYI, I've been working on eliminating Py_IDENTIFIER, instead statically allocating/initializing on PyInterpreterState. One thing I've noticed is that for almost every usage I can eliminate a branch (for whether or not the PyUnicodeObject is created). Likewise I drop the call to convert Py_Identifier to PyUnicodeObject. In about half the cases I can eliminate an extra call off the stack.

So there may be extra speedup from this that I wasn't expecting. 🙂

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants