Opened 9 months ago

Closed 9 months ago

Last modified 9 months ago

#35332 closed Cleanup/optimization (needsinfo)

Bad performance in django.template.load.render_to_string

Reported by: Zeyad Moustafa Owned by: nobody
Component: Template system Version: 5.0
Severity: Normal Keywords: performance templates jinja
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Hi folks, thanks for your great job here.

So with the rise of rust we are seeing, I told myself to make a component of Django components in rust so we can get a better performance as memory safety and all of these features from rust.

While searching I discovered a great package called mini-jinja. so I just wanted to compare its performance with the Django template engine performance to figure out if what I am doing is good for the community or not. so here is the code I have written to know about the performance.

# mini-jinja.py
from minijinja import Environment


with open('test.html', 'r') as file:
    template = file.read()


env = Environment(
    templates={
        'test': template
    }
)

result = env.render_template('test', nums=range(1000000))

and this is the result of the testing.

❯ time python mini-jinja.py
python mini-jinja.py  1.27s user 0.03s system 99% cpu 1.302 total

dummy/python-tests/copper via 🐍 v3.10.12 (.venv)
❯ time python mini-jinja.py
python mini-jinja.py  1.23s user 0.03s system 99% cpu 1.259 total

and this is how I tested it in django
first created main.py file with this contents

import time
from django.template.loader import render_to_string


def render():
    start = time.time()
    _template = render_to_string("test.html", {"nums": range(1000000)})
    end = time.time()
    print(end - start)

and then I opened the django shell and imported the main file and then typed render and here is what I got

❯ python manage.py shell
Python 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> import main
>>> main.render()
28.39499545097351
>>>

and here is the test.html I was using for both the tests

{% for num in nums%}

<h1>{{num}}</h1>

{% endfor %}

So here is my question. why a big difference between both of them?? is there anything I have done wrong or this is related to the nature of python?? I just opened this issue to know if it will be really good for the Django community to create a template engine using rust built on top of Mini-jinja or if there is something I have to modify in my tests to get the real result??

Change History (3)

comment:1 by Mariusz Felisiak, 9 months ago

Resolution: β†’ needsinfo
Status: new β†’ closed
Type: Uncategorized β†’ Cleanup/optimization

Hi, I don't think you've explained the issue in enough detail to confirm a bug in Django. Please reopen the ticket if you can debug your issue and provide details about why and where Django is at fault and what we could do better. Performance improvements are welcome, but you have to propose concrete things. You can start a discussion on the DevelopersMailingList, where you'll reach a wider audience and see what other think.

comment:2 by Adam Johnson, 9 months ago

Yeah, there’s no bug here. 30 times slowness is about right for a Rust/Python comparison. Also the benchmark is minimal and unrealistic, the margin should be less (maybe not much) for a typical template that has far fewer nodes.

This would be an interesting forum discussion - not a bug in the bug tracker. I’d be interested in seeing more. And if you want to get into optimizing specific parts of the template engine, I’d be up for reviewing some PRs. My recent work on the system checks may be a nice guide: ​https://adamj.eu/tech/2024/03/23/django-optimizing-system-checks/

comment:3 by Zeyad Moustafa, 9 months ago

OK. I opened a discussion here ​https://forum.djangoproject.com/t/getting-a-low-performance-in-django-template-loader-render-to-string/29488 and the person I was talking with told me the same thing that the benchmarking is not that good.

and I decided to make this template engine in rust. but I don't plan to integrate it into Django directly. I will start by building a standalone package and when I get a good community of people who are using it and testing it I might open a PR and integrate it to Django. but thanks for letting me know that you are interested in this idea.

Note: See TracTickets for help on using tickets.
Back to Top