Title: call_method(): call _PyObject_FastCall() rather than _PyObject_VaCallFunctionObjArgs()
Type: performance Stage:
Components: Interpreter Core Versions: Python 3.7
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: haypo, python-dev, serhiy.storchaka
Priority: normal Keywords:

Created on 2017-01-10 23:05 by haypo, last changed 2017-01-11 00:26 by haypo. This issue is now closed.

Messages (3)
msg285165 - (view) Author: STINNER Victor (haypo) * (Python committer) Date: 2017-01-10 23:05
Recently, I modified call_method() and call_maybe() of Objects/typeobject.c to avoid the creation of a temporary tuple: replace Py_VaBuildValue()+PyObject_Call() with the new _PyObject_VaCallFunctionObjArgs().

But while working on the issue #28870, I noticed that _PyObject_VaCallFunctionObjArgs() is not efficient and can be avoided. In typeobject.c, the number of arguments is hardcoded, so we don't need complex functions to compute the number of arguments and decide to allocate an array on the stack or on the heap.
msg285166 - (view) Author: Roundup Robot (python-dev) Date: 2017-01-10 23:22
New changeset b9404639a18c by Victor Stinner in branch 'default':
call_method() now uses _PyObject_FastCall()
msg285167 - (view) Author: STINNER Victor (haypo) * (Python committer) Date: 2017-01-10 23:22
Full commit message:

changeset:   106081:b9404639a18c
tag:         tip
user:        Victor Stinner <>
date:        Wed Jan 11 00:07:40 2017 +0100
files:       Include/abstract.h Objects/abstract.c Objects/typeobject.c
call_method() now uses _PyObject_FastCall()

Issue #29233: Replace the inefficient _PyObject_VaCallFunctionObjArgs() with
_PyObject_FastCall() in call_method() and call_maybe().

Only a few functions call call_method() and call it with a fixed number of
arguments. Avoid the complex and expensive _PyObject_VaCallFunctionObjArgs()
function, replace it with an array allocated on the stack with the exact number
of argumlents.

It reduces the stack consumption, bytes per call, before => after:

test_python_call: 1168 => 1152 (-16 B)
test_python_getitem: 1344 => 1008 (-336 B)
test_python_iterator: 1568 => 1232 (-336 B)

Remove the _PyObject_VaCallFunctionObjArgs() function which became useless.
Rename it to object_vacall() and make it private.
Date User Action Args
2017-01-11 00:26:53hayposetstatus: open -> closed
resolution: fixed
2017-01-10 23:22:57hayposetmessages: + msg285167
2017-01-10 23:22:32python-devsetnosy: + python-dev
messages: + msg285166
2017-01-10 23:14:42hayposettype: performance
components: + Interpreter Core
versions: + Python 3.7
2017-01-10 23:14:31hayposetnosy: + serhiy.storchaka
2017-01-10 23:05:00haypocreate