SlideShare ist ein Scribd-Unternehmen logo
1 von 22
Downloaden Sie, um offline zu lesen
High Performance Django

David Cramer
http://www.davidcramer.net/
http://www.ibegin.com/
Curse
•  Peak daily traffic of approx. 15m pages, 150m hits.

•  Average monthly traffic 120m pages, 6m uniques.

•  Python, MySQL, Squid, memcached, mod_python, lighty.

•  Most developers came strictly from PHP (myself included).

•  12 web servers, 4 database servers, 2 squid caches.
iBegin
•  Massive amounts of data, 100m+ rows.

•  Python, PHP, MySQL, mod_wsgi.

•  Small team of developers.

•  Complex database partitioning/synchronization tasks.

•  Attempting to not branch off of Django. 
Areas of Concern
•  Database (ORM)

•  Webserver (Resources, Handling Millions of Reqs)

•  Caching (Invalidation, Cache Dump)

•  Template Rendering (Logic Separation)

•  Profiling
Tools of the Trade
•  Webserver (Apache, Nginx, Lighttpd)

•  Object Cache (memcached)

•  Database (MySQL, PostgreSQL, …)

•  Page Cache (Squid, Nginx, Varnish)

•  Load Balancing (Nginx, Perlbal)
How We Did It

•  “Primary” web servers serving Django using mod_python.

•  Media servers using Django on lighttpd.

•  Static served using additional instances of lighttpd.

•  Load balancers passing requests to multiple Squids.

•  Squids passing requests to multiple web servers.
Lessons Learned
•  Don’t be afraid to experiment. You’re not limited to a one.

•  mod_wsgi is a huge step forward from mod_python.

•  Serving static files using different software can help.

•  Send proper HTTP headers where they are needed.

•  Use services like S3, Akamai, Limelight, etc..
Webserver Software
Python Scripts             Static Content
•  Apache (wsgi, mod_py,   •  Apache
   fastcgi)                •  Lighttpd
•  Lighttpd (fastcgi)      •  Tinyhttpd
•  Nginx (fastcgi)         •  Nginx
Reverse Proxies            Software Load Balancers
•  Nginx                   •  Nginx
•  Squid                   •  Perlbal
•  Varnish
Database (ORM)
•  Won’t make your queries efficient. Make your own indexes.

•  select_related() can be good, as well as bad.

•  Inherited ordering (Meta: ordering) will get you.

•  Hundreds of queries on a page is never a good thing.

•  Know when to not use the ORM.
Handling JOINs
class Category(models.Model):
     name       = models.CharField()
     created_by = models.ForeignKey(User)

class Poll(models.Model):
     name         = models.CharField()
     category     = models.ForeignKey(Category)
     created_by = models.ForeignKey(User)

# We need to output a page listing all Poll's with
# their name and category's name.

def a_bad_example(request):
     # We have just caused Poll to JOIN with User and Category,
     # which will also JOIN with User a second time.
     my_polls = Poll.objects.all().select_related()
     return render_to_response('polls.html', locals(), request)

def a_good_example(request):
     # Use select_related explicitly in each case.
     poll = Poll.objects.all().select_related('category')
     return render_to_response('polls.html', locals(), request)
Template Rendering
•  Sandboxed engines are typically slower by nature.

•  Keep logic in views and template tags.

•  Be aware of performance in loops, and groupby (regroup).

•  Loaded templates can be cached to avoid disk reads.

•  Switching template engines is easy, but may not give you

  any worthwhile performance gain.
Template Engines
Caching
•  Two flavors of caching: object cache and browser cache.

•  Django provides built-in support for both.

•  Invalidation is a headache without a well thought out plan.

•  Caching isn’t a solution for slow loading pages or improper indexes.

•  Use a reverse proxy in between the browser and your web servers:

   Squid, Varnish, Nginx, etc..
Cache With a Plan
•  Build your pages to use proper cache headers.

•  Create a plan for object cache expiration, and invalidation.

•  For typical web apps you can serve the same cached page

  for both anonymous and authenticated users.

•  Contain commonly used querysets in managers for

  transparent caching and invalidation.
Cache Commonly Used Items
def my_context_processor(request):
    # We access object_list every time we use our context processors so
    # it makes sense to cache this, no?
    cache_key = ‘mymodel:all’
    object_list = cache.get(cache_key)
    if object_list is None:
         object_list = MyModel.objects.all()
         cache.set(cache_key, object_list)
    return {‘object_list’: object_list}

# Now that we are caching the object list we are going to want to invalidate it
class MyModel(models.Model):
    name = models.CharField()

    def save(self, *args, **kwargs):
        super(MyModel, self).save(*args, **kwargs)
        # save it before you update the cache
        cache.set(‘mymodel:all’, MyModel.objects.all())
Profiling Code
•  Finding the bottleneck can be time consuming.

•  Tools exist to help identify common problematic areas.

   –  cProfile/Profile Python modules.

   –  PDB (Python Debugger)
Profiling Code With cProfile
import sys
try: import cProfile as profile
except ImportError: import profile
try: from cStringIO import StringIO
except ImportError: import StringIO
from django.conf import settings

class ProfilerMiddleware(object):
   def can(self, request):
     return settings.DEBUG and 'prof' in request.GET and (not settings.INTERNAL_IPS or request.META['REMOTE_ADDR'] in
       settings.INTERNAL_IPS)
   def process_view(self, request, callback, callback_args, callback_kwargs):
     if self.can(request):
         self.profiler = profile.Profile()
       args = (request,) + callback_args
       return self.profiler.runcall(callback, *args, **callback_kwargs)
  def process_response(self, request, response):
    if self.can(request):
        self.profiler.create_stats()
       out = StringIO()
       old_stdout, sys.stdout = sys.stdout, out
       self.profiler.print_stats(1)
       sys.stdout = old_stdout
       response.content = '<pre>%s</pre>' % out.getvalue()
     return response
http://localhost:8000/?prof
Profiling Database Queries
from django.db import connection
class DatabaseProfilerMiddleware(object):
  def can(self, request):
    return settings.DEBUG and 'dbprof' in request.GET 
       and (not settings.INTERNAL_IPS or 
       request.META['REMOTE_ADDR'] in settings.INTERNAL_IPS)

  def process_response(self, request, response):
    if self.can(request):
        out = StringIO()
        out.write('timetsqln')
        total_time = 0
        for query in reversed(sorted(connection.queries, key=lambda x: x['time'])):
         total_time += float(query['time'])*1000
         out.write('%st%sn' % (query['time'], query['sql']))

       response.content = '<pre style=quot;white-space:pre-wrapquot;>%d queries executed in %.3f secondsnn%s</pre>' %
    (len(connection.queries), total_time/1000, out.getvalue())
    return response
http://localhost:8000/?dbprof
Summary
•  Database efficiency is the typical problem in web apps.

•  Develop and deploy a caching plan early on.

•  Use profiling tools to find your problematic areas. Don’t pre-

  optimize unless there is good reason.

•  Find someone who knows more than me to configure your

  server software. 
Thanks!

Slides and code available online at:
http://www.davidcramer.net/djangocon

Weitere ähnliche Inhalte

Was ist angesagt?

You must know about CodeIgniter Popular Library
You must know about CodeIgniter Popular LibraryYou must know about CodeIgniter Popular Library
You must know about CodeIgniter Popular Library
Bo-Yi Wu
 
Python & Django TTT
Python & Django TTTPython & Django TTT
Python & Django TTT
kevinvw
 
The Best (and Worst) of Django
The Best (and Worst) of DjangoThe Best (and Worst) of Django
The Best (and Worst) of Django
Jacob Kaplan-Moss
 
Flask patterns
Flask patternsFlask patterns
Flask patterns
it-people
 

Was ist angesagt? (20)

Django a whirlwind tour
Django   a whirlwind tourDjango   a whirlwind tour
Django a whirlwind tour
 
Scalable Django Architecture
Scalable Django ArchitectureScalable Django Architecture
Scalable Django Architecture
 
Django for Beginners
Django for BeginnersDjango for Beginners
Django for Beginners
 
You must know about CodeIgniter Popular Library
You must know about CodeIgniter Popular LibraryYou must know about CodeIgniter Popular Library
You must know about CodeIgniter Popular Library
 
Python & Django TTT
Python & Django TTTPython & Django TTT
Python & Django TTT
 
Flask – Python
Flask – PythonFlask – Python
Flask – Python
 
Django Introduction & Tutorial
Django Introduction & TutorialDjango Introduction & Tutorial
Django Introduction & Tutorial
 
Django by rj
Django by rjDjango by rj
Django by rj
 
The Best (and Worst) of Django
The Best (and Worst) of DjangoThe Best (and Worst) of Django
The Best (and Worst) of Django
 
Salesforce CLI Cheat Sheet
Salesforce CLI Cheat Sheet Salesforce CLI Cheat Sheet
Salesforce CLI Cheat Sheet
 
HTML5 JavaScript APIs
HTML5 JavaScript APIsHTML5 JavaScript APIs
HTML5 JavaScript APIs
 
The DOM is a Mess @ Yahoo
The DOM is a Mess @ YahooThe DOM is a Mess @ Yahoo
The DOM is a Mess @ Yahoo
 
Filling the flask
Filling the flaskFilling the flask
Filling the flask
 
HTML5: friend or foe (to Flash)?
HTML5: friend or foe (to Flash)?HTML5: friend or foe (to Flash)?
HTML5: friend or foe (to Flash)?
 
The Django Web Application Framework
The Django Web Application FrameworkThe Django Web Application Framework
The Django Web Application Framework
 
Apache and PHP: Why httpd.conf is your new BFF!
Apache and PHP: Why httpd.conf is your new BFF!Apache and PHP: Why httpd.conf is your new BFF!
Apache and PHP: Why httpd.conf is your new BFF!
 
Flask patterns
Flask patternsFlask patterns
Flask patterns
 
Flask Basics
Flask BasicsFlask Basics
Flask Basics
 
Django Framework Overview forNon-Python Developers
Django Framework Overview forNon-Python DevelopersDjango Framework Overview forNon-Python Developers
Django Framework Overview forNon-Python Developers
 
Web development with django - Basics Presentation
Web development with django - Basics PresentationWeb development with django - Basics Presentation
Web development with django - Basics Presentation
 

Ähnlich wie High Performance Django

D Trace Support In My Sql Guide To Solving Reallife Performance Problems
D Trace Support In My Sql Guide To Solving Reallife Performance ProblemsD Trace Support In My Sql Guide To Solving Reallife Performance Problems
D Trace Support In My Sql Guide To Solving Reallife Performance Problems
MySQLConference
 

Ähnlich wie High Performance Django (20)

PyGrunn 2017 - Django Performance Unchained - slides
PyGrunn 2017 - Django Performance Unchained - slidesPyGrunn 2017 - Django Performance Unchained - slides
PyGrunn 2017 - Django Performance Unchained - slides
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web Apps
 
[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC
 
D Trace Support In My Sql Guide To Solving Reallife Performance Problems
D Trace Support In My Sql Guide To Solving Reallife Performance ProblemsD Trace Support In My Sql Guide To Solving Reallife Performance Problems
D Trace Support In My Sql Guide To Solving Reallife Performance Problems
 
mongodb-introduction
mongodb-introductionmongodb-introduction
mongodb-introduction
 
Automated Frontend Testing
Automated Frontend TestingAutomated Frontend Testing
Automated Frontend Testing
 
Openstack 簡介
Openstack 簡介Openstack 簡介
Openstack 簡介
 
Future of Web Apps: Google Gears
Future of Web Apps: Google GearsFuture of Web Apps: Google Gears
Future of Web Apps: Google Gears
 
Nanoformats
NanoformatsNanoformats
Nanoformats
 
All I Need to Know I Learned by Writing My Own Web Framework
All I Need to Know I Learned by Writing My Own Web FrameworkAll I Need to Know I Learned by Writing My Own Web Framework
All I Need to Know I Learned by Writing My Own Web Framework
 
Django tricks (2)
Django tricks (2)Django tricks (2)
Django tricks (2)
 
RubyEnRails2007 - Dr Nic Williams - Keynote
RubyEnRails2007 - Dr Nic Williams - KeynoteRubyEnRails2007 - Dr Nic Williams - Keynote
RubyEnRails2007 - Dr Nic Williams - Keynote
 
What's new in Django 1.2?
What's new in Django 1.2?What's new in Django 1.2?
What's new in Django 1.2?
 
Django Pro ORM
Django Pro ORMDjango Pro ORM
Django Pro ORM
 
Good practices for PrestaShop code security and optimization
Good practices for PrestaShop code security and optimizationGood practices for PrestaShop code security and optimization
Good practices for PrestaShop code security and optimization
 
Php classes in mumbai
Php classes in mumbaiPhp classes in mumbai
Php classes in mumbai
 
Sinatra and JSONQuery Web Service
Sinatra and JSONQuery Web ServiceSinatra and JSONQuery Web Service
Sinatra and JSONQuery Web Service
 
Django Multi-DB in Anger
Django Multi-DB in AngerDjango Multi-DB in Anger
Django Multi-DB in Anger
 
Django Show
Django ShowDjango Show
Django Show
 
6 tips for improving ruby performance
6 tips for improving ruby performance6 tips for improving ruby performance
6 tips for improving ruby performance
 

Mehr von DjangoCon2008

Mehr von DjangoCon2008 (6)

Why I Hate Django
Why I Hate DjangoWhy I Hate Django
Why I Hate Django
 
Pinax
PinaxPinax
Pinax
 
Satchmo
SatchmoSatchmo
Satchmo
 
Reusable Apps
Reusable AppsReusable Apps
Reusable Apps
 
What’S New In Newforms Admin
What’S New In Newforms AdminWhat’S New In Newforms Admin
What’S New In Newforms Admin
 
High Performance Django 1
High Performance Django 1High Performance Django 1
High Performance Django 1
 

Kürzlich hochgeladen

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 

Kürzlich hochgeladen (20)

Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 

High Performance Django

  • 1. High Performance Django David Cramer http://www.davidcramer.net/ http://www.ibegin.com/
  • 2. Curse •  Peak daily traffic of approx. 15m pages, 150m hits. •  Average monthly traffic 120m pages, 6m uniques. •  Python, MySQL, Squid, memcached, mod_python, lighty. •  Most developers came strictly from PHP (myself included). •  12 web servers, 4 database servers, 2 squid caches.
  • 3. iBegin •  Massive amounts of data, 100m+ rows. •  Python, PHP, MySQL, mod_wsgi. •  Small team of developers. •  Complex database partitioning/synchronization tasks. •  Attempting to not branch off of Django. 
  • 4. Areas of Concern •  Database (ORM) •  Webserver (Resources, Handling Millions of Reqs) •  Caching (Invalidation, Cache Dump) •  Template Rendering (Logic Separation) •  Profiling
  • 5. Tools of the Trade •  Webserver (Apache, Nginx, Lighttpd) •  Object Cache (memcached) •  Database (MySQL, PostgreSQL, …) •  Page Cache (Squid, Nginx, Varnish) •  Load Balancing (Nginx, Perlbal)
  • 6. How We Did It •  “Primary” web servers serving Django using mod_python. •  Media servers using Django on lighttpd. •  Static served using additional instances of lighttpd. •  Load balancers passing requests to multiple Squids. •  Squids passing requests to multiple web servers.
  • 7. Lessons Learned •  Don’t be afraid to experiment. You’re not limited to a one. •  mod_wsgi is a huge step forward from mod_python. •  Serving static files using different software can help. •  Send proper HTTP headers where they are needed. •  Use services like S3, Akamai, Limelight, etc..
  • 8. Webserver Software Python Scripts Static Content •  Apache (wsgi, mod_py, •  Apache fastcgi) •  Lighttpd •  Lighttpd (fastcgi) •  Tinyhttpd •  Nginx (fastcgi) •  Nginx Reverse Proxies Software Load Balancers •  Nginx •  Nginx •  Squid •  Perlbal •  Varnish
  • 9. Database (ORM) •  Won’t make your queries efficient. Make your own indexes. •  select_related() can be good, as well as bad. •  Inherited ordering (Meta: ordering) will get you. •  Hundreds of queries on a page is never a good thing. •  Know when to not use the ORM.
  • 10. Handling JOINs class Category(models.Model): name = models.CharField() created_by = models.ForeignKey(User) class Poll(models.Model): name = models.CharField() category = models.ForeignKey(Category) created_by = models.ForeignKey(User) # We need to output a page listing all Poll's with # their name and category's name. def a_bad_example(request): # We have just caused Poll to JOIN with User and Category, # which will also JOIN with User a second time. my_polls = Poll.objects.all().select_related() return render_to_response('polls.html', locals(), request) def a_good_example(request): # Use select_related explicitly in each case. poll = Poll.objects.all().select_related('category') return render_to_response('polls.html', locals(), request)
  • 11. Template Rendering •  Sandboxed engines are typically slower by nature. •  Keep logic in views and template tags. •  Be aware of performance in loops, and groupby (regroup). •  Loaded templates can be cached to avoid disk reads. •  Switching template engines is easy, but may not give you any worthwhile performance gain.
  • 13. Caching •  Two flavors of caching: object cache and browser cache. •  Django provides built-in support for both. •  Invalidation is a headache without a well thought out plan. •  Caching isn’t a solution for slow loading pages or improper indexes. •  Use a reverse proxy in between the browser and your web servers: Squid, Varnish, Nginx, etc..
  • 14. Cache With a Plan •  Build your pages to use proper cache headers. •  Create a plan for object cache expiration, and invalidation. •  For typical web apps you can serve the same cached page for both anonymous and authenticated users. •  Contain commonly used querysets in managers for transparent caching and invalidation.
  • 15. Cache Commonly Used Items def my_context_processor(request): # We access object_list every time we use our context processors so # it makes sense to cache this, no? cache_key = ‘mymodel:all’ object_list = cache.get(cache_key) if object_list is None: object_list = MyModel.objects.all() cache.set(cache_key, object_list) return {‘object_list’: object_list} # Now that we are caching the object list we are going to want to invalidate it class MyModel(models.Model): name = models.CharField() def save(self, *args, **kwargs): super(MyModel, self).save(*args, **kwargs) # save it before you update the cache cache.set(‘mymodel:all’, MyModel.objects.all())
  • 16. Profiling Code •  Finding the bottleneck can be time consuming. •  Tools exist to help identify common problematic areas. –  cProfile/Profile Python modules. –  PDB (Python Debugger)
  • 17. Profiling Code With cProfile import sys try: import cProfile as profile except ImportError: import profile try: from cStringIO import StringIO except ImportError: import StringIO from django.conf import settings class ProfilerMiddleware(object): def can(self, request): return settings.DEBUG and 'prof' in request.GET and (not settings.INTERNAL_IPS or request.META['REMOTE_ADDR'] in settings.INTERNAL_IPS) def process_view(self, request, callback, callback_args, callback_kwargs): if self.can(request): self.profiler = profile.Profile() args = (request,) + callback_args return self.profiler.runcall(callback, *args, **callback_kwargs) def process_response(self, request, response): if self.can(request): self.profiler.create_stats() out = StringIO() old_stdout, sys.stdout = sys.stdout, out self.profiler.print_stats(1) sys.stdout = old_stdout response.content = '<pre>%s</pre>' % out.getvalue() return response
  • 19. Profiling Database Queries from django.db import connection class DatabaseProfilerMiddleware(object): def can(self, request): return settings.DEBUG and 'dbprof' in request.GET and (not settings.INTERNAL_IPS or request.META['REMOTE_ADDR'] in settings.INTERNAL_IPS) def process_response(self, request, response): if self.can(request): out = StringIO() out.write('timetsqln') total_time = 0 for query in reversed(sorted(connection.queries, key=lambda x: x['time'])): total_time += float(query['time'])*1000 out.write('%st%sn' % (query['time'], query['sql'])) response.content = '<pre style=quot;white-space:pre-wrapquot;>%d queries executed in %.3f secondsnn%s</pre>' % (len(connection.queries), total_time/1000, out.getvalue()) return response
  • 21. Summary •  Database efficiency is the typical problem in web apps. •  Develop and deploy a caching plan early on. •  Use profiling tools to find your problematic areas. Don’t pre- optimize unless there is good reason. •  Find someone who knows more than me to configure your server software. 
  • 22. Thanks! Slides and code available online at: http://www.davidcramer.net/djangocon