New submission from Vladimir Matveev <desco...@gmail.com>:
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 ---------- components: Interpreter Core messages: 389114 nosy: v2m priority: normal severity: normal status: open title: Use dedicated opcodes to speed up calls/attribute lookups with super() as receiver versions: Python 3.10 _______________________________________ Python tracker <rep...@bugs.python.org> <https://bugs.python.org/issue43563> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com