New submission from Anselm Kruis <a.kr...@science-computing.de>:

Just a minor performance issue.

The C functions _PyFunction_FastCallDict() and _PyFunction_FastCallKeywords() 
(branch 'master', Objects/call.c) and their predecessors fast_function() and 
_PyFunction_FastCallDict() in Python/ceval.c all contain the following 
sub-expression in the "if"-statement for the fast-path. For instance 
Objects/call.c:318

 co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)

Now, if co_flags has any of the CO_FUTURE_... bits set, the expression is 
always False and the fast path is not used.

Currently this affects only Python 3.6 and Python 2.7, because other Python 
versions do not use the __future__ mechanism.

The fix is simple. Replace the faulty sub-expression by

 (co->co_flags & (~PyCF_MASK)) == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE))

I discovered this issue while debugging reference leaks in Stackless Python a 
few month ago. It is hard to write a test case, but one can compare C call 
stacks using a debugger.

$ ulimit -c unlimited  # enable core dumps
$ python3.6 -c 'from __future__ import generator_stop; import os; (lambda: 
os.abort())()'
$ gdb -batch -ex bt  python3.6 core > trace_with_future
$ python3.6 -c 'import os; (lambda: os.abort())()'
$ gdb -batch -ex bt  python3.6 core > trace_without_future

If you compare the traces, the difference is in stack frame #9. Same for 
python2.7.

----------
components: Interpreter Core
messages: 304702
nosy: anselm.kruis
priority: normal
severity: normal
status: open
title: _PyFunction_FastCallDict and _PyFunction_FastCallKeywords: fast path not 
used
type: performance
versions: Python 2.7, Python 3.6

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue31835>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to