[issue26802] Avoid copy in call_function_var when no extra stack args are passed

Joe Jevnik report at bugs.python.org
Tue Apr 19 04:00:58 EDT 2016


Joe Jevnik added the comment:

in _PyEval_EvalCodeWithName we will have already pulled the underlying array out of the tuple subclass and the then we will reconstruct the vararg value in the locals from this array. This means that with this patch we can get:

>>> class C(tuple): pass
... 
>>> def f(*args): print(type(args))
... 
>>> f(*C([1, 2, 3]))
<class 'tuple'>

The only case where we get potentially strange behavior is if we have a type whose tp_call did not forward to PyArg_Parse* or the PyTupleObject api and went though the abstract object interface. I ran the tests and the benchmark suite and did not run into any issues here but I can see how this would be potentially problematic behavior.

I have updated the code to also do a PyTuple_CheckExact against `stararg`. The tests I ran are:

timeit("h(*(a, b, c, d, e, f, g))", 'def h(a, b, c, d, e, f, g): pass\na, b, c, d, e, f, g = range(7)', number=int(10e7))

default: 17.191688070015516
patch: 14.060781285981648

There is also a really great case where you star unpack a tuple of literals which gets pushed into the co_consts:

timeit("f(*('a', 'b', 'c', 'd', 'e', 'f', 'g'))", 'def f(a, b, c, d, e, f, g): pass', number=int(10e7))

default: 13.842308042978402
patch: 9.696972723002546

This case seems far less common, but maybe someone has something like:

a = 1, 2, 3
...
f(*a)

----------
type: performance -> 
Added file: http://bugs.python.org/file42515/call-function-var.patch

_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue26802>
_______________________________________


More information about the Python-bugs-list mailing list