On Apr 8, 2020, at 09:57, Guido van Rossum <[email protected]> wrote:
>
>
> Look at the following code.
>
> def foo(a, b):
> x = a + b
> if not x:
> return None
> sleep(1) # A calculation that does not use x
> return a*b
>
> This code DECREFs x when the frame is exited (at the return statement). But
> (assuming) we can clearly see that x is not needed during the sleep
> (representing a big calculation), we could insert a "del x" statement before
> the sleep.
>
> I think our compiler is smart enough to find out *some* cases where it could
> safely insert such del instructions.
It depends on how much you’re willing to break and still call it “safely”.
def sleep(n):
global store
store = inspect.current_frame().f_back.f_locals['x']
This is a ridiculous example, but it shows that you can’t have all of Python’s
dynamic functionality and still know when locals are dead. And there are less
ridiculous examples with different code. If foo actually calls eval, exec,
locals, vars, etc., or if it has a nested function that nonlocals x, etc., how
can we spot that at compile time and keep x alive?
Maybe that’s ok. After all, that code doesn’t work in a Python implementation
that doesn’t have stack frame support. Some of the other possibilities might be
more portable, but I don’t know without digging in further.
Or maybe you can add new restrictions to what locals and eval and so on
guarantee that will make it ok? Some code will break, but only rare “expert”
code, where the authors will know how to work around it.
Or, if not, it’s definitely fine as an opt-in optimization: decorate the
function with @deadlocals and that decorator scans the bytecode and finds any
locals that are dead assuming there’s no use of locals/eval/cells/etc. and,
because you told it to assume that by opting in to the decorator, it can insert
a DELETE_FAST safely.
People already do similar things today—e.g., I’ve (only once in live code, but
that’s still more than zero) used a @fastconst decorator that turns globals
into consts on functions that I know are safe and are bottlenecks, and this
would be no different. And of course you can add a recursive class decorator,
or an import hook (or maybe even a command line flag or something) that enables
it everywhere (maybe with a @nodeadlocals decorator for people who want it
_almost_ everywhere but need to opt out one or two functions).
Did Victor Stinner explore this as one of the optimizations for FAT Python/PEP
511/etc.? Maybe not, since it’s not something you can insert a guard,
speculatively do, and then undo if the guard triggers, which was I think his
key idea.
_______________________________________________
Python-ideas mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/OIGCRV464VJW3FRRBBK25XSNQYGWID7N/
Code of Conduct: http://python.org/psf/codeofconduct/