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

Performing optimizations in the presence of Py_DECREF() #582

Open
markshannon opened this issue May 16, 2023 · 8 comments
Open

Performing optimizations in the presence of Py_DECREF() #582

markshannon opened this issue May 16, 2023 · 8 comments
Labels
epic-tier2-optimizer Linear code region optimizer for 3.13 and beyond.

Comments

@markshannon
Copy link
Member

We want to be able to optimize larger regions of code than a single instruction, but we can't (at least not as effectively) if arbitrary code can run in the middle of region. Py_DECREF() can run arbitrary code.

We should change Py_DECREF() so that it cannot run arbitrary code. Currently Py_DECREF(op) calls _Py_Dealloc(op) which calls Py_TYPE(op)->tp_dealloc(op).

We can modify _Py_Dealloc(op) to check a flag to see if there is a safe dealloc. If the dealloc is safe then call it, otherwise add the object to a queue to be deallocated later. Presumably on the eval breaker check.

This is going to slow down _Py_Dealloc, but hopefully not by much, and certainly less than the speedups that will be enabled.


An alternative approach is to make all the decrefs explicit in the IR and move them to the end of the superblock. This is IMO more complex and also prevents carrying optimizations across superblock boundaries.

Original discussion: #402

@markshannon markshannon added the epic-tier2-optimizer Linear code region optimizer for 3.13 and beyond. label May 16, 2023
@gvanrossum
Copy link
Collaborator

What's a safe dealloc though? Freeing a string or int, sure. But freeing a tuple has to ask the question recursively, because the tuple might contain something with a refcount equal to 1 whose dealloc is not safe; same for all containers (e.g. essentially all class instances).

@markshannon
Copy link
Member Author

Freeing a tuple is safe because it only calls Py_XDECREF before freeing the memory.
Py_DECREF is safe because it only calls safe functions, deferring unsafe ones.

@gvanrossum
Copy link
Collaborator

So the only unsafe deallocs are ones that can directly invoke Python code (not via DECREF)? I guess that would include all instances of Python classes, or perhaps only instances of Python classes that define or inherit a __del__ method.

@brandtbucher
Copy link
Member

brandtbucher commented May 17, 2023

...or C extension types with tp_finalize, or tp_del, or a non-trivial tp_dealloc, or anything that supports weakrefs...

@gvanrossum
Copy link
Collaborator

Couldn't weakrefs be separately put on a queue that's processed later?

@brandtbucher
Copy link
Member

Probably, yeah.

@markshannon
Copy link
Member Author

Anything that's not "safe" goes on a queue for later.
That's anything that needs finalizing, has any weakrefs, or just has an opaque tp_dealloc that can do anything.
The tricky part is to check all that very quickly.

@markshannon
Copy link
Member Author

markshannon commented Oct 6, 2023

Looking at the new stats for micro-ops, it looks like the micro-ops that do not contain _Py_DECREF except on known safe objects (like int) account for something like 80% of the execution count.

So this may not be so urgent, although still worth doing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
epic-tier2-optimizer Linear code region optimizer for 3.13 and beyond.
Projects
None yet
Development

No branches or pull requests

3 participants