How to optimize Django performance?
-
Enable Caching - Use Django’s caching at different levels like view, template fragments, sites etc. to avoid repeating expensive queries. Use
@cached_property
to cache model properties. -
Optimize Database Performance - Profile queries using
explain()
and debug toolbar. Add indexes appropriately. Reduce queries and do work at DB level. Bulk create/update usingbulk_create()
,bulk_update()
. -
Keep Database Connections Alive - Set
CONN_MAX_AGE
to keep database connections alive and avoid overhead of reconnecting. -
Use Asynchronous Servers - Use WSGI servers like gunicorn to utilize async workers and support more concurrent connections.
-
Lazy Evaluation - Use lazy querysets instead of eager evaluation to optimize performance.
-
Profile Bottlenecks - Use tools like debug toolbar, django profiler, cProfile etc to identity bottlenecks.
-
Template Optimization - Cache fragments of templates, optimize number of blocks, avoid runtime heavy filters etc.
-
Limit Fetching Related Objects - Use
select_related()
andprefetch_related()
to optimize related object fetching. -
Do Operations in Bulk - Use bulk methods for CUD operations instead of multiple individual queries.
what is WSGI application ?
- WSGI defines a standard for python web apps to talk to web servers
- A WSGI app is a python callable that handles requests and returns response
- Django provides a WSGI app to run on WSGI compliant web servers
- WSGI decouples Django from its own server and makes it portable
why do we need gunicorn?
gunicorn is a WSGI HTTP server used to serve Django applications in production environments. Some key reasons we need gunicorn are:
-
Django’s development server is not suitable for production. It is single threaded and does not support concurrency or scaling.
-
Gunicorn is a WSGI HTTP server optimized for production usage. It supports multiprocessing, async workers, load balancing etc for high performance.
-
Gunicorn helps utilize multiple CPU cores by running multiple worker processes. This makes it ideal for serving django apps with traffic.
-
Gunicorn provides integration with monitoring tools for metrics, health checks etc.
-
Gunicorn can be configured with different WSGI containers like gevent, eventlet etc. for additional performance.
-
It supports HTTP keep-alive for persistent connections instead of closing connection per request.
-
Gunicorn helps run Django behind Nginx reverse proxy which provides additional benefits like static file serving, caching, SSL termination etc.
How to optimize Django ORM and database performance?
Some tips to optimize django ORM and database access:
- Profile database queries first using
queryset.explain()
and debug toolbar - Add indexes appropriately based on query patterns
- Reduce number of queries and do work at database level where possible
- Fetch related objects in single
select_related()
query instead of multiple queries - Use
prefetch_related()
to fetch related objects in bulk - Do write operations in bulk using
bulk_create()
,bulk_update()
instead of multiple queries - Keep database connections alive using
CONN_MAX_AGE
to avoid reconnection overhead
How does Django caching work?
Django provides multiple caching strategies:
- Low level cache API to cache arbitrary data
- Per-view cache to cache output of specific views
- Template fragment caching to cache portions of rendered template
- Per-site caching to cache entire site
Django caches are pluggable and can use memcache, redis etc as backend cache store.
Caching avoids executing expensive queries or operations multiple times and can significantly improve performance. But cache invalidation needs to be handled properly.
How can we profile a django application?
Some ways to profile a django application:
- Use django debug toolbar to get insights like number of queries, time taken, SQL generated etc
- Use django profiling middleware to profile view methods
- Use python profiling libraries like cProfile, line_profiler etc
- Profile database queries using
queryset.explain()
- Use tools like New Relic, Datadog, Sentry etc for application performance monitoring
Profiling helps identity specific bottlenecks like slow database queries, inefficient code etc which can then be optimized.