[Python-Dev] On the METH_FASTCALL calling convention
Victor Stinner
vstinner at redhat.com
Fri Jul 6 18:26:16 EDT 2018
Hi,
I designed FASTCALL with the help of Serhiy for keywords. I prepared a long
email reply, but I found an opportunity for optimisation on **kwargs and I
need time to see how to optimize it.
Maybe there is a need for passing **kwargs as a dict at C level, but use
FASTCALL for positional arguments? I only know dict.update() which would
benefit of that. All other functions are fine with FASTCALL for keywords.
Victor
Le vendredi 6 juillet 2018, Guido van Rossum <guido at python.org> a écrit :
> I'm not the world's leading expert on Python bytecode anymore, but unless
there's something I'm missing your conclusion looks eminently reasonable,
and so I expect you'll get very little traction on this thread. (If you had
wanted to get a megathread you should have written "FASTCALL considered
harmful". :-)
>
> I think there was one person in another thread (INADA Naoki?) who thought
METH_FASTCALL could use improvements. Maybe that person can write back to
this thread? Or perhaps Victor Stinner (who seems to have touched it last)
has a suggestion for what could be improved about it?
> --Guido
>
> On Thu, Jul 5, 2018 at 7:55 AM Jeroen Demeyer <J.Demeyer at ugent.be> wrote:
>>
>> Hello all,
>>
>> As discussed in some other threads ([1], [2]), we should discuss the
>> METH_FASTCALL calling convention.
>>
>> For passing only positional arguments, a C array of Python objects is
>> used, which is as fast as it can get. When the Python interpreter calls
>> a function, it builds that C array on the interpreter stack:
>>
>> >>> from dis import dis
>> >>> def f(x, y): return g(x, y, 12)
>> >>> dis(f)
>> 1 0 LOAD_GLOBAL 0 (g)
>> 2 LOAD_FAST 0 (x)
>> 4 LOAD_FAST 1 (y)
>> 6 LOAD_CONST 1 (12)
>> 8 CALL_FUNCTION 3
>> 10 RETURN_VALUE
>>
>> A C array can also easily and efficiently be handled by the C function
>> receiving it. So I consider this uncontroversial.
>>
>> The convention for METH_FASTCALL|METH_KEYWORDS is that keyword *names*
>> are passed as a tuple and keyword *values* in the same C array with
>> positional arguments. An example:
>>
>> >>> from dis import dis
>> >>> def f(x, y, z): return f(x, foo=y, bar=z)
>> >>> dis(f)
>> 1 0 LOAD_GLOBAL 0 (f)
>> 2 LOAD_FAST 0 (x)
>> 4 LOAD_FAST 1 (y)
>> 6 LOAD_FAST 2 (z)
>> 8 LOAD_CONST 1 (('foo', 'bar'))
>> 10 CALL_FUNCTION_KW 3
>> 12 RETURN_VALUE
>>
>> This is pretty clever: it exploits the fact that ('foo', 'bar') is a
>> constant tuple stored in f.__code__.co_consts. Also, a tuple can be
>> efficiently handled by the called code: it is essentially a thin wrapper
>> around a C array of Python objects. So this works well.
>>
>> The only case when this handling of keywords is suboptimal is when using
>> **kwargs. In that case, a dict must be converted to a tuple. It looks
>> hard to me to support efficiently both the case of fixed keyword
>> arguments (f(foo=x)) and a keyword dict (f(**kwargs)). Since the former
>> is more common than the latter, the current choice is optimal.
>>
>> In other words: I see nothing to improve in the calling convention of
>> METH_FASTCALL. I suggest to keep it and make it public as-is.
>>
>>
>> Jeroen.
>>
>>
>> [1] https://mail.python.org/pipermail/python-dev/2018-June/153945.html
>> [2] https://mail.python.org/pipermail/python-dev/2018-July/154251.html
>> _______________________________________________
>> Python-Dev mailing list
>> Python-Dev at python.org
>> https://mail.python.org/mailman/listinfo/python-dev
>> Unsubscribe:
https://mail.python.org/mailman/options/python-dev/guido%40python.org
>
>
> --
> --Guido van Rossum (python.org/~guido)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20180707/7f91d6d1/attachment.html>
More information about the Python-Dev
mailing list