114

My django application has become painfully slow on the production. Probably it is due to some complex or unindexed queries.

Is there any django-ish way to profile my application?

sharjeel
  • 5,825
  • 7
  • 34
  • 49

9 Answers9

95

Try the Django Debug Toolbar. It will show you what queries are executed on each page and how much time they take. It's a really useful, powerful and easy to use tool.

Also, read recommendations about Django performance in Database access optimization from the documentation.

And Django performance tips by Jacob Kaplan-Moss.

Mr. S
  • 1,469
  • 2
  • 15
  • 27
Silver Light
  • 44,202
  • 36
  • 123
  • 164
  • 17
    Watch out for Django Debug Toolbar - I turned it off during development and page rendering was significantly quicker on my (admittedly low-power) laptop - look in the dev server to see how much data you're downloading. – Dominic Rodger Mar 02 '10 at 13:32
  • 2
    django-debug-toolbar helps me to see how many queries django-orm hits the db, and we can see how select_related() function do the trick hitting it less. – panchicore Mar 02 '10 at 14:20
  • 14
    @dominic-rodger I didn't realize how much slower the Debug Toolbar made things process. My sql queries were small (30ms) but cpu time was very high (800ms). Another page i was tuning had sql times of 300ms, and cpu time of 8000ms - so i kept trying to find the source of the problem. Turning Django Toolbar off sped things right up. 3 years later, still relevant. – Esteban Jan 30 '13 at 18:59
  • 2
    @Esteban, thanks a lot for this comment, i was literally going nuts over the ridiculously high amount of CPU time, dhango toolbar took. With django profiling the CPU time was around 30 seconds, once i removed it, it came down to 1.5 seconds !! – noob Mama Feb 09 '15 at 05:23
29

Just type "django-profiling" on google, you'll get these links (and more):

http://code.djangoproject.com/wiki/ProfilingDjango

http://code.google.com/p/django-profiling/

http://www.rkblog.rk.edu.pl/w/p/django-profiling-hotshot-and-kcachegrind/

Personally I'm using the middleware approach - i.e. each user can toggle a "profiling" flag stored in a session, and if my profiling middleware notices that a flag has been set, it uses Python's hotshot module like this:

def process_view(self, request, view_func, view_args, view_kwargs):

     # setup things here, along with: settings.DEBUG=True 
     # to get a SQL dump in connection.queries

     profiler = hotshot.Profile(fname)
     response = profiler.runcall(view_func, request, *view_args, **view_kwargs)
     profiler.close()

     # process results

     return response

EDIT: For profiling SQL queries http://github.com/robhudson/django-debug-toolbar mentioned by Konstantin is a nice thing - but if your queries are really slow (probably because there are hundreds or thousands of them), then you'll be waiting insane amount of time until it gets loaded into a browser - and then it'll be hard to browse due to slowness. Also, django-debug-toolbar is by design unable to give useful insight into the internals of AJAX requests.

EDIT2: django-extensions has a great profiling command built in:

https://github.com/django-extensions/django-extensions/blob/master/docs/runprofileserver.rst

Just do this and voila:

$ mkdir /tmp/my-profile-data
$ ./manage.py runprofileserver --kcachegrind --prof-path=/tmp/my-profile-data
NuLo
  • 1,298
  • 1
  • 11
  • 16
Tomasz Zieliński
  • 16,136
  • 7
  • 59
  • 83
  • 7
    http://code.google.com/p/django-profile/ is a User Profile django application. it's not used as profiling django :) – dzen Mar 14 '11 at 16:52
  • 1
    @dzen: Hah, good point, it was meant to be: http://code.google.com/p/django-profiling/ :-) – Tomasz Zieliński Mar 14 '11 at 18:17
  • 1
    if you wonder how to read the profiler dumps after running `python manage.py runprofileserver --prof-path=/path/to/dir`, follow this blog: http://www.darkcoding.net/software/profiling-django-for-cpu-bound-apps/. – Neara Mar 20 '14 at 10:16
  • ah yes, my favorite, using google to find one of the top answers to my query is "just google the thing you googled to get here" – Anna Jan 11 '18 at 20:06
  • Note that `hotshot` has been deprecated and removed in Python 3, so this answer and the `ProfilingDjango` Wiki page may no longer be relevant in 20202. – Patryk Bratkowski Jul 16 '20 at 11:56
16

Shameless plug here, but I recently made https://github.com/django-silk/silk for this purpose. It's somewhat similar to django toolbar but with history, code profiling and more fine grained control over everything.

avelis
  • 1,143
  • 1
  • 9
  • 18
Michael
  • 2,258
  • 1
  • 23
  • 31
15

For profiling data access (which is where the bottleneck is most of the time) check out django-live-profiler. Unlike Django Debug Toolbar it collects data across all requests simultaneously and you can run it in production without too much performance overhead or exposing your app internals.

Check out this screenshot

Gourneau
  • 12,660
  • 8
  • 42
  • 42
atereshkin
  • 696
  • 5
  • 8
9

I needed to profile a Django app recently and tried many of these suggestions. I ended up using pyinstrument instead, which can be added to a Django app using a single update to the middleware list and provides a stack-based view of the timings.

Quick summary of my experience with some other tools:

  • Django Debug Toolbar is great if you the issue is due to SQL queries and works well in combination with pyinstrument
  • django-silk works well, but requires adding a context manager or decorator to each part of the stack where you want sub-request timings. It also provides an easy way to access cProfile timings and automatically displays ajax timings, both of which can be really helpful.
  • djdt-flamegraph looked promising, but the page never actually rendered on my system.

Compared to the other tools I tried, pyinstrument was dramatically easier to install and to use.

Tony S Yu
  • 3,003
  • 30
  • 40
6

For all you KCacheGrind fans, I find it's very easy to use the shell in tandem with Django's fantastic test Client for generating profile logs on-the-fly, especially in production. I've used this technique now on several occasions because it has a light touch — no pesky middleware or third-party Django applications are required!

For example, to profile a particular view that seems to be running slow, you could crack open the shell and type this code:

from django.test import Client
import hotshot

c = Client()
profiler = hotshot.Profile("yourprofile.prof")  # saves a logfile to your pwd
profiler.runcall(c.get, "/pattern/matching/your/view/")
profiler.close()

To visualize the resulting log, I've used hotshot2cachegrind:

But there are other options as well:

Joshua Pokotilow
  • 1,213
  • 9
  • 13
4

When the views are not HTML, for example JSON, use simple middleware methods for profiling.

Here are a couple examples:

https://gist.github.com/1229685 - capture all sql calls went into the view

https://gist.github.com/1229681 - profile all method calls used to create the view

Evgeny
  • 6,533
  • 5
  • 58
  • 64
2

You can use line_profiler.

It allows to display a line-by-line analysis of your code with the time alongside of each line (When a line is hit several times, the time is summed up also).

enter image description here

It's used with not-Django python code but there's a little trick to use it on Django in fact: https://stackoverflow.com/a/68163807/1937033

ThePhi
  • 2,373
  • 3
  • 28
  • 38
1

I am using silk for live profiling and inspection of Django application. This is a great tool. You can have a look on it.

https://github.com/jazzband/django-silk

Waqas Ali
  • 1,441
  • 2
  • 20
  • 25