This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author v2m
Recipients v2m
Date 2021-03-19.20:57:57
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1616187477.95.0.162642980766.issue43563@roundup.psfhosted.org>
In-reply-to
Content
Calling methods and lookup up attributes when receiver is `super()` has extra cost comparing to regular attribute lookup. It mainly comes from the need to allocate and initialize the instance of the `super` which for zero argument case also include peeking into frame/code object for the `__class__` cell and first argument. In addition because `PySuper_Type` has custom implementation of tp_getattro - `_PyObject_GetMethod` would always return bound method. 
```
import timeit

setup = """
class A:
    def f(self): pass
class B(A):
    def f(self): super().f()
    def g(self): A.f(self)
b = B()
"""
print(timeit.timeit("b.f()", setup=setup, number=20000000))
print(timeit.timeit("b.g()", setup=setup, number=20000000))

7.329449548968114
3.892987059080042
```
 
One option to improve it could be to make compiler/interpreter aware of super calls so they can be treated specially. Attached patch introduces two new opcodes LOAD_METHOD_SUPER and LOAD_ATTR_SUPER that are intended to be counterparts for LOAD_METHOD and LOAD_ATTR for cases when receiver is super with either zero or two arguments.

Immediate argument for both LOAD_METHOD_SUPER and LOAD_ATTR_SUPER is a pair that consist of:
 0: index of method/attribute in co_names
 1: Py_True if super was originally called with 0 arguments and Py_False otherwise.

Both LOAD_METHOD_SUPER and LOAD_ATTR_SUPER expect 3 elements on the stack:
TOS3: global_super
TOS2: type
TOS1: self/cls

Result of LOAD_METHOD_SUPER is the same as LOAD_METHOD.
Result of LOAD_ATTR_SUPER is the same as LOAD_ATTR

In runtime both LOAD_METHOD_SUPER and LOAD_ATTR_SUPER will check if `global_super` is `PySuper_Type` to handle situations when `super` is patched. If `global_super` is `PySuper_Type` then it can use dedicated routine to perform the lookup for provided `__class__` and `cls/self` without allocating new `super` instance. If `global_super` is different from `PySuper_Type` then runtime will fallback to the original logic using `global_super` and original number of arguments that was captured in immediate.

Benchmark results with patch:
4.381768501014449
3.9492998640052974
History
Date User Action Args
2021-03-19 20:57:57v2msetrecipients: + v2m
2021-03-19 20:57:57v2msetmessageid: <1616187477.95.0.162642980766.issue43563@roundup.psfhosted.org>
2021-03-19 20:57:57v2mlinkissue43563 messages
2021-03-19 20:57:57v2mcreate