Opened 19 months ago

Last modified 18 months ago

#34521 closed Cleanup/optimization

Use __slots__ for template Node classes — at Version 2

Reported by: Adam Johnson Owned by: nobody
Component: Template system Version: dev
Severity: Normal Keywords:
Cc: Keryn Knight, Carlton Gibson Triage Stage: Unreviewed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: yes
Easy pickings: no UI/UX: no

Description (last modified by Adam Johnson)

Declaring slots reduces the memory footprint of a class, and can lead to performance gains due to less data fetching by the CPU.

#12826 proposed adding slots to many classes but was closed with the proposal to do so on a case-by-case basis.

#33474 added slots to Variable and related classes, showing memory reductions and performance gains.

I propose adding slots to more template classes to further save memory (Template, Token, Lexer, and the Node classes). This change leads to 1-2% improvement in template rendering time, using this benchmark script:

import django
from django.conf import settings
from django.template import Context
from django.template import Template

settings.configure(
    TEMPLATES=[{"BACKEND": "django.template.backends.django.DjangoTemplates"}]
)
django.setup()

template = Template("{% if x %}{{ x }}{% endif %}" * 1_000)
context = Context({"x": "abc"})
for i in range(1_000):
    template.render(context)

And invoking [hyperfine](https://github.com/sharkdp/hyperfine) like so, with Python 3.11.2:

$ hyperfine \
  -N --warmup 1 \
  --prepare 'git switch -d 7d0e566208' \
  'python benchmark.py' \
  --prepare 'git switch ticket_34521_optimize_templates' \
  'python benchmark.py'
Benchmark 1: python benchmark.py
  Time (mean ± σ):      2.028 s ±  0.042 s    [User: 1.990 s, System: 0.035 s]
  Range (min … max):    1.997 s …  2.116 s    10 runs

Benchmark 2: python benchmark.py
  Time (mean ± σ):      1.985 s ±  0.007 s    [User: 1.950 s, System: 0.033 s]
  Range (min … max):    1.976 s …  1.997 s    10 runs

Summary
  'python benchmark.py' ran
    1.02 ± 0.02 times faster than 'python benchmark.py'

(I decided not to use djangobench since it's not well maintained, and doesn't do such great stats as hyperfine.)

Change History (2)

comment:1 by Adam Johnson, 19 months ago

Description: modified (diff)

comment:2 by Adam Johnson, 19 months ago

Description: modified (diff)
Note: See TracTickets for help on using tickets.
Back to Top