[issue44850] Could operator.methodcaller be optimized using LOAD_METHOD?

Antony Lee report at bugs.python.org
Fri Aug 6 06:42:14 EDT 2021


New submission from Antony Lee <anntzer.lee at gmail.com>:

Currently, methodcaller is not faster than a plain lambda:
```
In [1]: class T:
   ...:     a = 1
   ...:     def f(self): pass
   ...:     

In [2]: from operator import *

In [3]: %%timeit t = T(); mc = methodcaller("f")
   ...: mc(t)
   ...: 
   ...: 
83.1 ns ± 0.862 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [4]: %%timeit t = T(); mc = lambda x: x.f()
   ...: mc(t)
   ...: 
   ...: 
81.4 ns ± 0.0508 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
```
(on some machines, I find that it is even slower).

Compare with attrgetter, which *is* faster:
```
In [5]: %%timeit t = T(); ag = attrgetter("a")
   ...: ag(t)
   ...: 
   ...: 
33.7 ns ± 0.0407 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [6]: %%timeit t = T(); ag = lambda x: x.a
   ...: ag(t)
   ...: 
   ...: 
50.1 ns ± 0.057 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
```

Given that the operator module explicitly advertises itself as being "efficient"/"fast", it seems reasonable to try to optimize methodcaller.  Looking at its C implementation, methodcaller currently uses PyObject_GetAttr followed by PyObject_Call; I wonder whether this can be optimized using a LOAD_METHOD-style approach to avoid the construction of the bound method (when applicable)?

----------
components: Library (Lib)
messages: 399066
nosy: Antony.Lee
priority: normal
severity: normal
status: open
title: Could operator.methodcaller be optimized using LOAD_METHOD?

_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue44850>
_______________________________________


More information about the Python-bugs-list mailing list