Skip to content

Speed up method calls by avoiding bound method instantiation #2242

@scoder

Description

@scoder

Currently, method calls are split into an AttributeNode for the method lookup and a PyMethodCallNode for the call (see ExprNodes.py). Following an optimisation in CPython 3.7 (which brought about a 20% speedup), it would be nice to avoid the generic attribute lookup and replace it with a call to the __Pyx_PyObject_GetMethod() utility function, which can avoid the instantiation of a bound method object. Instead, the underlying function can be called as unbound method, passing the self argument explicitly.

Most of the infrastructure is already there, as well as a simpler optimisation in PyMethodCallNode that should be replaced by this one. Look for usages of the CYTHON_UNPACK_METHODS feature switch.

Design:

  • special-case and separate out the "plain Python attribute" case in PyMethodCallNode as follows:
  • evaluate all arguments in order, but not the argument tuple itself
  • for the 0, 1, 2 argument cases, simply call the helper functions __Pyx_PyObject_CallMethod[012](), otherwise:
  • create a PyObject*[] C array with length 1+len(args)
  • put the attribute owner object in the first index, followed by all arguments (all borrowed references)
  • write a call helper function (very similar to the ..._CallMethod() hepers, but generalised) that accepts the object, the method name, the argument array and the arguments count as input
  • make it call __Pyx_PyObject_GetMethod() to look up the method
  • make it special case fast-call Py/C-functions as in the current implementation (and like all the ..._CallMethod[012]() helpers do)
  • fall back to building a tuple and calling the function
  • include the first (self) argument in the array only when the GetMethod() was able to return an unbound (unpacked) method, and exclude it otherwise

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions