[New-bugs-announce] [issue40988] singledispatchmethod significantly slower than singledispatch
Federico Caselli
report at bugs.python.org
Mon Jun 15 16:14:13 EDT 2020
New submission from Federico Caselli <cfederico87 at gmail.com>:
The implementation of singledispatchmethod is significantly slower (~4x) than the normal singledispatch version
Using timeit to test this example case:
from functools import singledispatch, singledispatchmethod
import timeit
class Test:
@singledispatchmethod
def go(self, item, arg):
print('general')
@go.register
def _(self, item:int, arg):
return item + arg
@singledispatch
def go(item, arg):
print('general')
@go.register
def _(item:int, arg):
return item + arg
print(timeit.timeit('t.go(1, 1)', globals={'t': Test()}))
print(timeit.timeit('go(1, 1)', globals={'go': go}))
Prints on my system.
3.118346
0.713173
Looking at the singledispatchmethod implementation I believe that most of the difference is because a new function is generated every time the method is called.
Maybe an implementation similar to cached_property could be used if the class has __dict__ attribute?
Trying this simple patch
diff --git a/Lib/functools.py b/Lib/functools.py
index 5cab497..e42f485 100644
--- a/Lib/functools.py
+++ b/Lib/functools.py
@@ -900,6 +900,7 @@ class singledispatchmethod:
self.dispatcher = singledispatch(func)
self.func = func
+ self.attrname = None
def register(self, cls, method=None):
"""generic_method.register(cls, func) -> func
@@ -908,6 +909,10 @@ class singledispatchmethod:
"""
return self.dispatcher.register(cls, func=method)
+ def __set_name__(self, owner, name):
+ if self.attrname is None:
+ self.attrname = name
+
def __get__(self, obj, cls=None):
def _method(*args, **kwargs):
method = self.dispatcher.dispatch(args[0].__class__)
@@ -916,6 +921,7 @@ class singledispatchmethod:
_method.__isabstractmethod__ = self.__isabstractmethod__
_method.register = self.register
update_wrapper(_method, self.func)
+ obj.__dict__[self.attrname] = _method
return _method
@property
improves the performance noticeably
0.9720976
0.7269078
----------
components: Library (Lib)
messages: 371594
nosy: CaselIT
priority: normal
severity: normal
status: open
title: singledispatchmethod significantly slower than singledispatch
type: performance
versions: Python 3.8
_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue40988>
_______________________________________
More information about the New-bugs-announce
mailing list