diff options
| author | Ran Benita <ran234@gmail.com> | 2019-05-03 13:34:05 +0300 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2023-06-08 09:17:50 +0200 |
| commit | ee36e101e8f8c0acde4bb148b738ab7034e902a0 (patch) | |
| tree | 34e965eada5bd7333a6c8349b4092b9a50173ea3 /django/utils | |
| parent | a57d5d9bbc27a7c3f18e14f68cfc74477b50eda0 (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.py | 23 |
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()) |
