summaryrefslogtreecommitdiff
path: root/django/utils
diff options
context:
space:
mode:
authorRan Benita <ran234@gmail.com>2019-05-03 13:34:05 +0300
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2023-06-08 09:17:50 +0200
commitee36e101e8f8c0acde4bb148b738ab7034e902a0 (patch)
tree34e965eada5bd7333a6c8349b4092b9a50173ea3 /django/utils
parenta57d5d9bbc27a7c3f18e14f68cfc74477b50eda0 (diff)
Optimized lazy() by removing use of @total_ordering.
@total_ordering is slow. Using the following micro-benchmark (resultclasses intentionally omitted to narrow the scope): import cProfile from django.utils.functional import lazy def identity(x): return x cProfile.run("for i in range(10000): str(lazy(identity)(1))") Before: 380003 function calls in 0.304 seconds ncalls tottime percall cumtime percall filename:lineno(function) 1 0.016 0.016 0.304 0.304 <string>:1(<module>) 10000 0.002 0.000 0.002 0.000 bench.py:5(double) 10000 0.005 0.000 0.006 0.000 functional.py:100(__cast) 10000 0.007 0.000 0.013 0.000 functional.py:106(__str__) 10000 0.005 0.000 0.017 0.000 functional.py:140(__wrapper__) 10000 0.020 0.000 0.258 0.000 functional.py:60(lazy) 10000 0.039 0.000 0.039 0.000 functional.py:68(__proxy__) 10000 0.010 0.000 0.012 0.000 functional.py:77(__init__) 10000 0.002 0.000 0.002 0.000 functional.py:84(__prepare_class__) 10000 0.025 0.000 0.075 0.000 functools.py:186(total_ordering) 10000 0.015 0.000 0.028 0.000 functools.py:189(<setcomp>) 10000 0.024 0.000 0.044 0.000 functools.py:37(update_wrapper) 10000 0.005 0.000 0.005 0.000 functools.py:67(wraps) 10000 0.074 0.000 0.114 0.000 {built-in method builtins.__build_class__} 1 0.000 0.000 0.304 0.304 {built-in method builtins.exec} 150000 0.023 0.000 0.023 0.000 {built-in method builtins.getattr} 10000 0.004 0.000 0.004 0.000 {built-in method builtins.max} 80000 0.025 0.000 0.025 0.000 {built-in method builtins.setattr} 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 10000 0.003 0.000 0.003 0.000 {method 'update' of 'dict' objects} After: 240003 function calls in 0.231 seconds ncalls tottime percall cumtime percall filename:lineno(function) 1 0.016 0.016 0.231 0.231 <string>:1(<module>) 10000 0.002 0.000 0.002 0.000 bench.py:5(double) 10000 0.006 0.000 0.012 0.000 functional.py:105(__str__) 10000 0.005 0.000 0.017 0.000 functional.py:159(__wrapper__) 10000 0.015 0.000 0.186 0.000 functional.py:60(lazy) 10000 0.022 0.000 0.022 0.000 functional.py:68(__proxy__) 10000 0.010 0.000 0.012 0.000 functional.py:76(__init__) 10000 0.002 0.000 0.002 0.000 functional.py:83(__prepare_class__) 10000 0.004 0.000 0.006 0.000 functional.py:99(__cast) 10000 0.023 0.000 0.043 0.000 functools.py:37(update_wrapper) 10000 0.004 0.000 0.004 0.000 functools.py:67(wraps) 10000 0.102 0.000 0.124 0.000 {built-in method builtins.__build_class__} 1 0.000 0.000 0.231 0.231 {built-in method builtins.exec} 70000 0.011 0.000 0.011 0.000 {built-in method builtins.getattr} 50000 0.007 0.000 0.007 0.000 {built-in method builtins.setattr} 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 10000 0.003 0.000 0.003 0.000 {method 'update' of 'dict' objects}
Diffstat (limited to 'django/utils')
-rw-r--r--django/utils/functional.py23
1 files changed, 21 insertions, 2 deletions
diff --git a/django/utils/functional.py b/django/utils/functional.py
index 66d88d9b59..6ee630c021 100644
--- a/django/utils/functional.py
+++ b/django/utils/functional.py
@@ -1,7 +1,7 @@
import copy
import itertools
import operator
-from functools import total_ordering, wraps
+from functools import wraps
class cached_property:
@@ -82,7 +82,6 @@ def lazy(func, *resultclasses):
function is evaluated on every access.
"""
- @total_ordering
class __proxy__(Promise):
"""
Encapsulate a function call and act as a proxy for methods that are
@@ -144,11 +143,31 @@ def lazy(func, *resultclasses):
other = other.__cast()
return self.__cast() == other
+ def __ne__(self, other):
+ if isinstance(other, Promise):
+ other = other.__cast()
+ return self.__cast() != other
+
def __lt__(self, other):
if isinstance(other, Promise):
other = other.__cast()
return self.__cast() < other
+ def __le__(self, other):
+ if isinstance(other, Promise):
+ other = other.__cast()
+ return self.__cast() <= other
+
+ def __gt__(self, other):
+ if isinstance(other, Promise):
+ other = other.__cast()
+ return self.__cast() > other
+
+ def __ge__(self, other):
+ if isinstance(other, Promise):
+ other = other.__cast()
+ return self.__cast() >= other
+
def __hash__(self):
return hash(self.__cast())