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 <gu...@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.deme...@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@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)
_______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com