Message399066
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)? |
|
| Date |
User |
Action |
Args |
| 2021-08-06 10:42:14 | Antony.Lee | set | recipients:
+ Antony.Lee |
| 2021-08-06 10:42:14 | Antony.Lee | set | messageid: <1628246534.03.0.387871214532.issue44850@roundup.psfhosted.org> |
| 2021-08-06 10:42:14 | Antony.Lee | link | issue44850 messages |
| 2021-08-06 10:42:13 | Antony.Lee | create | |
|