[New-bugs-announce] [issue42873] Exponential time and space requirements for compilation of nested try/finally blocks
Mark Dickinson
report at bugs.python.org
Sat Jan 9 07:00:18 EST 2021
New submission from Mark Dickinson <dickinsm at gmail.com>:
tl;dr - contrived (but relatively short) code involving nested try/finally blocks can produce disproportionately large bytecode. I'm not expecting or suggesting any action here, but the situation seemed at least worth noting. Feel free to close this issue as a "well don't do that, then" (a.k.a. "wont fix")
Longer: Python 3.9 changed the way that bytecode was generated for try/finally (see #33387). For a "try" block body that can do any of raise, return or fall-off-the-end-of-the-block, the corresponding finally block gets three separate paths in the bytecode. If such trys are nested <n> times, we get 3^n separate paths in the bytecode.
Example code:
----------------
def f():
try:
if something(): return
finally:
try:
if something(): return
finally:
try:
if something(): return
finally:
try:
if something(): return
finally:
try:
if something(): return
finally:
do_cleanup()
import dis
dis.dis(f)
----------------
On my machine, running this and counting the do_cleanup invocations gives, as expected, a result of 243 = 3**5
% python3.9 nested_finally.py | grep do_cleanup | wc -l
243
That's fairly benign, but if I scale up to 10 nested blocks, the dis.dis call takes over 10 minutes to complete (the compilation itself still only takes a fraction of a second). The bytecode object is correspondingly large:
>>> len(f.__code__.co_code)
1741356
With 15 levels of nesting, compilation takes several seconds, and
the generated code is (again as expected) a couple of orders of magnitude larger:
>>> len(f.__code__.co_code)
533859040
I didn't try pushing this further than 15 levels of nesting.
As I said above, it's not clear to me whether this is actually an issue that needs to be addressed in practice. It seems unlikely that "real code" :TM: would run into this, but the effect seemed worth noting.
----------
components: Interpreter Core
messages: 384718
nosy: Mark.Shannon, mark.dickinson
priority: normal
severity: normal
status: open
title: Exponential time and space requirements for compilation of nested try/finally blocks
type: performance
versions: Python 3.10, Python 3.9
_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue42873>
_______________________________________
More information about the New-bugs-announce
mailing list