2. Speed is a feature
A mystical journey through Django performance
optimization techniques, tools and gotchas
@martinblech @polmuz
3. Roadmap
How to find performance problems
Sneak peak: Front-end performance
How to fix them in Django
4. Why?
[Google] found that Half a
second delay caused a 20% drop
in traffic.
[Amazon] found that even very
small delays would result in
substantial and costly drops in
revenue.
Users really respond to speed
2006
5. There’s nothing like data
Don’t start with the code. Profile and gather real usage data.
6. There’s nothing like real data
Identify bottlenecks
New Relic
Very good
Very paid
Google Analytics
Free of charge
Less detail
Your logs
No data to third parties
Harder to use
Profiling
Complex setup required
Overhead
15. select_related()
>>> for c in Comment.objects.all():
print c.user.name
# select * from comments;
# select * from users where id = 1;
# select * from users where id = 2;
...
>>> comments = Comment.objects.all();
>>> for c in comments.select_related(“user”):
print c.user.name
# select comments.*, users.*
# from comments, users
# where comments.user_id = users.id;
16. prefech_related()
>>> for u in User.objects.filter(id__lt=10):
print len(u.comments.all())
# select * from users;
# select * from comments where user_id = 1;
# select * from comments where user_id = 2;
...
>>> users = User.objects.filter(id__lt=10)
>>> for u in users.prefetch_related(“comments”):
print len(u.comments.all())
# select * from users where id < 10;
# select * from comments
# where user_id in (1,2,3,4,5,6,7,8,9);
## Joins them in python
24. Caching!
from django.core.cache import get_cache
cache = get_cache('default')
def last_comments(request):
comments_ids = cache.get('last_comments')
if comments_ids:
comments = Comment.objects.filter(id__in=comments_ids)
else:
comments = fetch_last_comments()
comments_ids = [c.id for c in comments]
cache.set('last_comments', comments_ids)
...
Low level cache API
25. Cache Invalidation
“There are two hard things in computer
science: cache invalidation, naming
things, and off-by-one errors.”
post_save/post_delete are a good place
to start, but it doesn’t end there!
@receiver(post_save, sender=Comment)
@receiver(post_delete, sender=Comment)
def invalidate_last_comments(sender, **kwargs):
cache.delete('last_comments')
27. Don’t forget about the browser
80% or more of the end-user response
time is spent in the front end
Combine
Compress
Cache
Less is more
Load slow things later
Focus on making the
important things faster
28. Don’t forget about the browser
Google PageSpeed Insights
webpagetest.org
Chrome & Firefox