﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
30498	lazy() class preparation is not being cached correctly.	Ran Benita	Ran Benita	"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:

{{{#!python
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}
}}}"	Cleanup/optimization	closed	Utilities	dev	Normal	fixed			Accepted	1	0	0	0	0	0
