Opened 5 years ago
Closed 5 years ago
#30498 closed Cleanup/optimization (fixed)
lazy() class preparation is not being cached correctly.
Reported by: | Ran Benita | Owned by: | Ran Benita |
---|---|---|---|
Component: | Utilities | Version: | dev |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Accepted | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Doing self.__prepared = True
changes the instance, but the intention is to change the class variable: https://github.com/django/django/blob/888fdf182e164fa4b24aa82fa833c90a2b9bee7a/django/utils/functional.py#L82
This makes functions like gettext_lazy, format_lazy and reverse_lazy a lot slower than they ought to be.
Regressed in Django 1.8 (b4e76f30d12bfa8a53cc297c60055c6f4629cc4c).
Using this micro-benchmark on Python 3.7:
import cProfile from django.utils.functional import lazy def identity(x): return x lazy_identity = lazy(identity, int) cProfile.run("for i in range(10000): str(lazy_identity(1))")
Before:
910049 function calls in 0.208 seconds Ordered by: standard name ncalls tottime percall cumtime percall filename:lineno(function) 1 0.010 0.010 0.208 0.208 <string>:1(<module>) 10000 0.001 0.000 0.001 0.000 bench.py:4(identity) 10000 0.005 0.000 0.010 0.000 functional.py:105(__str__) 10000 0.004 0.000 0.188 0.000 functional.py:159(__wrapper__) 10000 0.007 0.000 0.185 0.000 functional.py:76(__init__) 10000 0.089 0.000 0.178 0.000 functional.py:83(__prepare_class__) 10000 0.004 0.000 0.005 0.000 functional.py:99(__cast) 1 0.000 0.000 0.208 0.208 {built-in method builtins.exec} 840000 0.087 0.000 0.087 0.000 {built-in method builtins.hasattr} 46 0.000 0.000 0.000 0.000 {built-in method builtins.setattr} 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 10000 0.002 0.000 0.002 0.000 {method 'mro' of 'type' objects}
After:
50135 function calls in 0.025 seconds Ordered by: standard name ncalls tottime percall cumtime percall filename:lineno(function) 1 0.008 0.008 0.025 0.025 <string>:1(<module>) 10000 0.001 0.000 0.001 0.000 bench.py:4(identity) 10000 0.005 0.000 0.009 0.000 functional.py:105(__str__) 10000 0.003 0.000 0.008 0.000 functional.py:159(__wrapper__) 10000 0.005 0.000 0.005 0.000 functional.py:76(__init__) 1 0.000 0.000 0.000 0.000 functional.py:83(__prepare_class__) 10000 0.004 0.000 0.005 0.000 functional.py:99(__cast) 1 0.000 0.000 0.025 0.025 {built-in method builtins.exec} 84 0.000 0.000 0.000 0.000 {built-in method builtins.hasattr} 46 0.000 0.000 0.000 0.000 {built-in method builtins.setattr} 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 1 0.000 0.000 0.000 0.000 {method 'mro' of 'type' objects}
Change History (3)
comment:1 by , 5 years ago
Has patch: | set |
---|
comment:2 by , 5 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
Summary: | lazy() class preparation is not being cached correctly → lazy() class preparation is not being cached correctly. |
Triage Stage: | Unreviewed → Accepted |
Thanks for the report! Reproduced at 888fdf182e164fa4b24aa82fa833c90a2b9bee7a.
PR: https://github.com/django/django/pull/11399