#26095: Same behaviour of dict.items and defaultdict.items in DTL
-------------------------------------+-------------------------------------
     Reporter:  kbr                  |                    Owner:  kbr
         Type:                       |                   Status:  closed
  Cleanup/optimization               |
    Component:  Template system      |                  Version:  master
     Severity:  Normal               |               Resolution:  wontfix
     Keywords:  templates dict       |             Triage Stage:
  defaultdict                        |  Unreviewed
    Has patch:  1                    |      Needs documentation:  1
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------

Comment (by kbr):

 Some final thoughts, but at the very beginning: I'm in no way annoyed that
 the patch doesn't get merged!

 As funkybob mentioned, isinstance is called for every step of every
 lookup. So a template like this will cause 4 additional calls:

 {{{
 {% for k, v in d.items %}{{ k }}:{{ v }}{% endfor %}
 }}}

 I have set up a tiny script (with 1000 times the above snippet) for some
 simple profiling to get a feeling for the impact:

 {{{
 from django.template.base import Context
 from django.template.engine import Engine

 s = '{% for k, v in d.items %}{{ k }}:{{ v }}{% endfor %}'
 d = {'one': [1]}
 n = 1000
 s *= n

 engine = Engine()
 t = engine.from_string(s)
 context = Context({'d': d,})
 #res = t.render(context)
 }}}

 The last line is commented out to get the overhead for preparing the
 template and the context. Calling 'python -m cProfile -s cumulativ
 _profile.py' now gives a fairly large output:

 {{{
 322295 function calls (316792 primitive calls) in 0.420 seconds
 ...
 20469    0.005    0.000    0.005    0.000 {built-in method isinstance}
 }}}

 isinstance() gets called 20469 times. Most of these calls are because of
 's *= n'. Uncommenting the last line now renders with the unpatched
 version:

 {{{
 464331 function calls (455828 primitive calls) in 0.543 seconds
 ...
 50472    0.012    0.000    0.012    0.000 {built-in method isinstance}
 }}}

 shows that isinstance gets called excessively and takes about 7 ms
 additional runtime.
 Rendering with the patched version should produce even 4k more calls:

 {{{
 468330 function calls (459827 primitive calls) in 0.517 seconds
 ...
 54471    0.013    0.000    0.013    0.000 {built-in method isinstance}
 }}}

 This is the case and runs 1 ms longer.

 To prepare a context for 4k lookups it may take some additional time for
 accessing a db and the template may not come from a prepared string but
 from another io-channel. All in all I think that the impact of the patch
 is insignificant.

 @funkybob: you further mentioned a precedent. Well, that may be a point.
 IMHO it's quiet ok to expect as least surprise using dicts and
 defaultdicts as these datatypes are builtins resp. from the standard
 library. One can not assume that individual modified classes derived from
 these types will have no unexpected behaviour in the way the DTL-lookup
 works. But that's just my opinion and there may be other ones.

--
Ticket URL: <https://code.djangoproject.com/ticket/26095#comment:9>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-updates+unsubscr...@googlegroups.com.
To post to this group, send email to django-updates@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/061.a3f5db4be3bfb5fb3f4af60cec4ad29f%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to