-
-
Notifications
You must be signed in to change notification settings - Fork 30.4k
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
Disable automatic update of frame locals during tracing #86363
Comments
Right now, when a debugger is active, the number of local variables can affect the tracing speed quite a lot. For instance, having tracing setup in a program such as the one below takes 4.64 seconds to run, yet, changing all the variables to have the same name -- i.e.: change all assignments to
This happens because So, I'd like to simply remove those calls. Debuggers can call As for i.e.: something as the code below prints the Line 35 in cb9879b
So, the idea is removing those lines (I expect that I'll be able to provide a pull request for this). |
Fabio created a thread on python-dev: In 2017, Nick Coghlan wrote the PEP-558 "Defined semantics for locals()". |
Mark: do you think that it's an acceptable trade-off to ask debuggers and profilers to call explicitly PyFrame_FastToLocalsWithError() and PyFrame_LocalsToFast(), to optimize the common case, when locals are not needed? |
I don't think so. PEP-558 should help, as f_locals becomes a proxy. Ultimately, what we need is a decent debugger API, something along the lines of the JVMTI. |
I agree that it can be made better, but I think most of the issues right now comes from CPython trying to automatically do something that's not bound to work (calling PyFrame_FastToLocals/PyFrame_LocalsToFast under the hood during the tracing call). https://bugs.python.org/issue30744 is a great example of why that can never work properly (debuggers need to manage that much more carefully, just doing it on all calls is really bound to not work). So, the current implementation besides being broken also makes things pretty slow. I agree that PEP-558 may fix things here (but it's much more work). As a disclaimer, pydevd actually uses a different tracer which doesn't do those calls and when possible uses the frame eval to modify the bytecode directly to minimize the overhead, so, in practice the current support given by CPython for debugger is pretty reasonable for doing a fast debugger (but there are a few caveats that it must work around -- such as the auto PyFrame_FastToLocals/PyFrame_LocalsToFast calls). |
I've updated PEP-558 with a reference back to this ticket as additional motivation (the update also addresses several of the fragility concerns that Mark raised): python/peps#1787 There's still work to be done to bring the reference implementation into line with the updated proposal, but I'm making it an explicit goal to get the proposal submitted for pronouncement in time for inclusion in 3.11. |
@ncoghlan I took a quick look at the PEP... I'm a bit worried about:
In particular, it's common for a debugger to evaluate expressions in a context that would change the locals to add new variables. i.e.: stopping at a breakpoint and doing 2 So, it's expected that Right now after each line of the evaluation, a p.s.: should I ask such questions regarding the PEP somewhere else instead of this issue or is this an appropriate place? |
If a function does not have the local variables |
Right now such changes are visible to the debugee in the locals frames if a user does the So, it's the difference between being able to import a module and creating/manipulating new variables in an |
While the various frame and debugger PEPs that are open offer a better solution to this, they might not be accepted for 3.11. So I'd like to revisit this. Removing the calls to Using Fabio's example I get the following slowdowns: This is quite a compelling reason to remove the calls to The questions is "what will we break doing this"? Ned, how would this impact coverage.py? |
Off the top of my head, I'm not sure this affects coverage.py at all, but I could be missing something. Does PR 23028 have all the changes, or is there some other python/cpython branch I can test with? |
Yes the PR has all the changes. It is just the changes sysmodule.c that you need: |
Or you can use this branch: |
As I already wrote previously, I'm a supporter of requiring debuggers and profilers to explicitly call PyFrame_FastToLocalsWithError() and PyFrame_LocalsToFast(). It should only impact a minority of users, whereas the majority will benefit of way better performance, no? |
I ran the coverage.py test suite using https://github.com/faster-cpython/cpython/tree/dont-fast-to-locals-in-trampoline, and there were no failures. |
And btw, the tests with that branch ran at least twice as fast as with 3.10....! |
See also bpo-47092: [C API] Add PyFrame_GetVar(frame, name) function. |
Mark: Please add the new PyFrame_GetLocals() function to the C API > New Features doc: |
f_locals
dictionary unless we actually need it. #32055Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: