Joshua,
My team is producing a Django app with a small number of
users, so we haven't worried too much about performance yet,
but we know we may have to some day, so I've accumulated a
list of ways to improve performance in a JIRA ticket for if/when
it becomes a priority.
We've done some of them already, with a quick and easy
thousand-fold increase in speed.
Here's a cut/paste of our ideas. I hope you find it useful.
Optimize the site for speed
- I/O speed
- Prime candidate #3. May be costing us
at least a couple seconds.
Easy fix
- Especially to phones with slow Internet connections
- Minimize the size of the HTML, JS, CSS and image files
- Combine CSS into a single file, and JS into a single
file
- Minify the HTML, JS, and CSS
- Compress (zip) the HTML, JS, and CSS
- May want to use gulp to minify and compress.
See:
- Move CSS to the top and JS to the bottom of HTML
files
- See "How to improve web page performance from
RevSys" below
- http://www.revsys.com/12days/front-end-performance/
- New HTML5 "Picture" element ("art direction"
technique) and CSS calc() function to optimize image
download speed:
- Limit the size of image files uploaded by the patients.
Scale them smaller as they are uploaded if necessary.
- Optimize caching by browsers
- Far future expires headers
- Version number embedded in resource names for force
re-load at new release
- CPU speed
- Do as much as possible in JS on the local device, not in
Python/Django on the shared server
- Disk speed
- Use the AWS Console to change the disk drives of the
server from magnetic
disks to SSDs.
- Set up a RAID volume
- DB speed
- Do all selects/joins/filtering in the DB. Do not query
lots of data
from the DB and then iterate over it or otherwise filter
it in Python.
Especially, do not query lots of data from the DB, pass it
all to the
browser, and iterate over it or otherwise filter it in
_javascript_.
- Create DB indexes for all fields used frequently in
SELECTs
- Move the DB server to a different Linux server than the
Web server, to split the load between 2 servers, if the DB
is the bottleneck. Use Amazon RDS
- http://www.revsys.com/12days/finding-sources-of-slowness/
- EXPLAIN PLAN
- EXPLAIN ANALYZE
- Django DB speed:
- Monitoring DB access:
- select_related
- prefetch_related
- Optimize Django's ORM access to DB:
- Add Django multi-column DB indexes
- Ajax
- Use Ajax partial page loads instead of full page loads
- Use Ajax to load rest of page while the user already has
something to look at.
- Don't get too chatty
- Going back to the server on each keystroke for
autocomplete is a heavy load. Might be better to wait
a second or so after each keystroke to see if the user
is still typing, using the same kind of algorithm Fred
has used in the past, and that Google uses for
auto-suggestions at Google Search.
- 12/10/2012: Changed to use a 300 ms delay for
now.
- Should perhaps also delay search till 3 chars
typed, instead of current
2 chars
- Django server-side caching
- Prime candidate #1. May be costing us
at least a couple seconds.
- Django Template Caching
- Prime candidate #1a. May be
costing us at least a couple seconds.
- Status: Done. Dramatic
improvement.
- Django page caching
- Also, "Varnish" as an alternative to standard Django
caching. See:
- Also caching of template pages via template tag {% cache
%}
- Or is this just part of standard Django caching?
- Could also re-order the INSTALLED_APPS list so that the
apps with
the most frequently loaded templates come first. That
would make
'django.template.loaders.app_directories.Loader' more
efficient.
- Not likely to matter since we're already doing
template file
caching. But if we ever stop using that...
- Could also give up on the less efficient
'django.template.loaders.app_directories.Loader', and just
use
'django.template.loaders.filesystem.Loader' which only
looks in
one location, not one per app. Especially since we include
the
app name in the reference to each template already. Could
just
create a single templates folder with app names as
subfolders.
- Not likely to matter since we're already doing
template file
caching. But if we ever stop using that...
- DB caching
- Prime candidate #2. May be costing us
at least a couple seconds.
Easy fix
- Set up a distributed DB cache like memcached
- Warning: If we use caching, search for the word
"cache" here to find ways to prevent the PROD cache from
being used for testing. Otherwise, we may corrupt the PROD
DB during testing.
- Turn on automatic Django SQL query logging, and watch
for frequent or slow queries
- Web Server speed
- Apache httpd server
- Optimal number of processes, threads, connections,
open files
- nginx instead of Apache
- App Server (Django/WSGI) speed
- Optimal number of processes, threads specified for WSGI
in Apache httpd.conf file:
- WSGIDaemonProcess wsgi_apps processes=2 threads=15
- http://www.revsys.com/12days/nginx-tuning/
- uWSGI instead of mod_wsgi, to connect Apache to Django
- Caching on the phone
- We may need to consider some caching of data on the
phones
- Have to be prepared for sluggish performance because
some phones will be in areas with poor cell phone
reception.
- Especially for repetitive actions like Event Checkout.
- Re-write specific pages to be faster
- Cache HTTP sessions, not in the DB:
- Scaling (vertical and horizontal):
- Prime candidate #5. We really should
not need to do this, but it's
a cheap and easy way to get a quick fix,
if none of the other
prime candidates work well enough.
- Vertically -- larger servers
- Horizontally -- more servers
Enjoy!
On 2/3/16 10:30 AM, Joshua Pokotilow
wrote:
At the startup where I work,
we've written a lot of our server code in Django. So far,
we've adopted a "build it fast" mentality, so we invested very
little time in optimizing our code. A small amount of load
testing has revealed our codebase / infrastructure as it
stands today needs to run faster and support more users.
We recently hired some new engineers who are
extremely skeptical that we should optimize our existing code.
Their main concerns are:
- We need to move to a service-oriented
infrastructure because Django is too monolithic (monolithic =
technology lock-in & difficult to troubleshoot)
- It's too easy to write slow queries using
the Django ORM
- It's hard to hire Django engineers
- While Instagram and DISQUS use Django to
service large numbers of people, they don't use it for any
serious backend work
After having worked with Django for the last
3 years, I'm a big believer in it, and I believe it would
scale. To defend my position, I've pointed out to my
colleagues that it's easy to identify bottlenecks with tools
like the Django Debug Toolbar and Yet Another Django Profiler.
With my colleagues present, I've isolated and fixed
significant speed problems inside of a few hours. I don't
believe the Django ORM is inherently bad, although I do think
that coders who use it should Know What They're Doing.
Finally, I've referenced blog entries that talk about how
Instagram and Disqus use Django on the backend for backend-y
tasks.
Despite my best efforts, my colleagues are
still pushing to have us rewrite large portions of our
infrastructure as separate services before we try to fix them.
For example, we have one slow REST endpoint that returns a
boatload of user data, and so there's talk about using a new
microservice for users in lieu of our existing Django models.
Even if we are able to fix bottlenecks we encounter in a
timely fashion, my colleagues fear that Django won't scale
with the business.
I'm writing this post to garner additional
evidence that Django will scale. Anything compelling (and
preferably not obvious) that would help shed some light on
Django's ability to scale would be *greatly* appreciated, as
it's very difficult for me to defend my position that Django
is a viable long-term solution without solid evidence to
back up my claims. It certainly doesn't help that I don't
have any experience scaling Django myself!
Thank you.
--
You received this message because you are subscribed to the Google
Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it,
send an email to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/83968c41-d415-4189-b33b-9f99b10b1c41%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/56B25293.3090205%40bristle.com.
For more options, visit https://groups.google.com/d/optout.
|