Some profiling shows template rendering as the culprit. (I'm trying on a page with ONLY cached queries.) But still, the template is very simple. the most complex part is a nested loop that runs for 10 times, but if everything goes well the nested loop doesn't run because it's cached. (like in my testing)
that is
{% for p in posts %}
--{{p.by.username}}
--{{p.text}}
{% cache 600 p p.timestamp %}
{% for img in p.images.all %}
--{{img.path}}
{% endfor %}
{% endcache %}
{% endfor %}
I get ~80 req/s on the dev. server for this page. (I found I can multiply that number by 3 in the production deploy) For a comparison, I get 1000req/s for a trivial template that only contains a short static string.
Is that a known issue? How do I go about correcting/avoiding it?
Django sites can be slow if you use the convenience naively. If a Django application is noticeably slow it is almost always inefficient use of the ORM, which can be fixed in an afternoon with a profile or debug toolbar. If it is okayish but not fast then it is usually because of a lack of cache strategy.
Django is not slow. Instagram was built on it, and all these years later they're still using the core request-response handlers.
Built by experienced developers, it takes care of much of the hassle of web development, so you can focus on writing your app without needing to reinvent the wheel. It's free and open source. Ridiculously fast. Django was designed to help developers take applications from concept to completion as quickly as possible.
In development mode, django does a lot of things to ease developing(for example: code reloading; template rendering for every request if template used; ...).
In production mode, deploy a WSGI server before django is preferred. Such wsgi might be gunicorn, uWSGI, ...
A typical production web server's layout might be: nginx -> gunicorn -> django
A simple comparison(django official tutorial code with a very simple "Hello World! @ time" template):
{% block content %}
<p> Hello World! @ {{ now }}</p>
{% endblock %}
python manage.py runserver
ab -n1000 -c10 http://127.0.0.1:8000/polls/helloworld
Server Software: WSGIServer/0.2 # django
Server Hostname: 127.0.0.1
Server Port: 8000
Document Path: /polls/helloworld
Document Length: 59 bytes
Concurrency Level: 10
Time taken for tests: 3.438 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 242000 bytes
HTML transferred: 59000 bytes
Requests per second: 290.87 [#/sec] (mean)
Time per request: 34.380 [ms] (mean)
Time per request: 3.438 [ms] (mean, across all concurrent requests)
Transfer rate: 68.74 [Kbytes/sec] received
../bin/gunicorn -w4 mysite.wsgi # with 4 workers
ab -n1000 -c10 http://127.0.0.1:8000/polls/helloworld
Server Software: gunicorn/19.7.1 # gunicorn
Server Hostname: 127.0.0.1
Server Port: 8000
Document Path: /polls/helloworld
Document Length: 59 bytes
Concurrency Level: 10
Time taken for tests: 0.618 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 248000 bytes
HTML transferred: 59000 bytes
Requests per second: 1619.10 [#/sec] (mean)
Time per request: 6.176 [ms] (mean)
Time per request: 0.618 [ms] (mean, across all concurrent requests)
Transfer rate: 392.13 [Kbytes/sec] received
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With