Saturday 26 December 2015

Django Profiler

Django profiler

Recently I have used many profilers in python which got me thinking about using profiler in a django app. So I started searching for ways to use a profiler in django. I have tried integrating many python profiler in django app's views.py file but it didn't go well as I expected. But then I tried to remove the profile added in the py file and used python's builtin profiler cProfile. I used the following command to execute python profiler along with the django runserver.
 
   $ python -m cProfile manage.py runserver

At first I couldn't figure out the way to get the profiler output while running the django dev server. As soon as I terminate the server the profiler output began to display in the terminal. Yes I got an output from profile but not the expected way. The present generated profiler output was the profiler output of the all the django process from the beginning of the server starting which is not easy to go through especially the list was too long. So I continued the R&D and finally reached at a py file which is added as a middleware file in django. Way the profiler work is like this after starting the server you can access the profiler data by typing ?prof which will open the profiler output of the current page in the browser. The profiler code is mentioned below.
 
try:
    import cProfile as profile
except ImportError:
    import profile

try:
    from cStringIO import StringIO
except:
    from io import StringIO

import pstats
from django.conf import settings


class ProfilerMiddleware(object):
    """
    Simple profile middleware to profile django views. To run it, add ?prof to
    the URL like this:

        http://localhost:8000/view/?prof

    Optionally pass the following to modify the output:

    ?sort => Sort the output by a given metric. Default is time.
        See http://docs.python.org/2/library/profile.html#pstats.Stats.sort_stats
        for all sort options.

    ?count => The number of rows to display. Default is 100.

    This is adapted from an example found here:
    http://www.slideshare.net/zeeg/django-con-high-performance-django-presentation.
    """
    def can(self, request):
        return settings.DEBUG and 'prof' in request.GET and \
            request.user is not None and request.user.is_staff

    def process_view(self, request, callback, callback_args, callback_kwargs):
        if self.can(request):
            self.profiler = profile.Profile()
            args = (request,) + callback_args
            try:
                return self.profiler.runcall(callback, *args, **callback_kwargs)
            except:
                # we want the process_exception middleware to fire
                # https://code.djangoproject.com/ticket/12250
                return

    def process_response(self, request, response):
        if self.can(request):
            self.profiler.create_stats()
            io = StringIO()
            stats = pstats.Stats(self.profiler, stream=io)
            stats.strip_dirs().sort_stats(request.GET.get('sort', 'time'))
            stats.print_stats(int(request.GET.get('count', 100)))
            response.content = '<pre>%s</pre>' % io.getvalue()
        return response

Steps:

  • Copy paste the code to file and save it as .py file.
  • Add the file to the MIDDLEWARE_CLASSES section in djnago settings.py file.
  • Run the django server.
  • To see the profiler add '?prof' after the url in the browser. (eg: http://12.0.0.1:8000/home/?prof )
For other profilers for django app:
     Profiling Django
     Django Live Profiler

No comments:

Post a Comment