You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import sys
  2. import tempfile
  3. import hotshot
  4. import hotshot.stats
  5. from cStringIO import StringIO
  6. import cProfile
  7. import pstats
  8. def profile_this(fn):
  9. def profiled_fn(*args, **kwargs):
  10. filepath = "/tmp/%s.profile" % fn.__name__
  11. prof = cProfile.Profile()
  12. ret = prof.runcall(fn, *args, **kwargs)
  13. print "Writing to %s" % filepath
  14. prof.dump_stats(filepath)
  15. print "Printing stats"
  16. stats = pstats.Stats(filepath)
  17. stats.sort_stats('cumulative')
  18. stats.print_stats()
  19. return ret
  20. return profiled_fn
  21. class BaseMiddleware(object):
  22. query_param = None
  23. def show_profile(self, request):
  24. return self.query_param in request.GET
  25. def process_request(self, request):
  26. if self.show_profile(request):
  27. if 'prof_file' in request.GET:
  28. # It's sometimes useful to generate a file of output that can
  29. # converted for use with kcachegrind. To convert this file,
  30. # use:
  31. #
  32. # pyprof2calltree -o /tmp/callgrind.stats -i /tmp/out.stats
  33. #
  34. # then open the file in kcachegrind.
  35. self.tmpfile = open('/tmp/out.stats', 'w')
  36. else:
  37. self.tmpfile = tempfile.NamedTemporaryFile()
  38. self.profile = self.profiler()
  39. def profiler(self):
  40. return None
  41. def process_view(self, request, callback, callback_args, callback_kwargs):
  42. # We profile the view call - note that this misses the rest of Django's
  43. # request processing (eg middleware etc)
  44. if self.show_profile(request):
  45. return self.profile.runcall(
  46. callback, request, *callback_args, **callback_kwargs)
  47. def process_response(self, request, response):
  48. if self.show_profile(request):
  49. stats = self.stats()
  50. if 'prof_strip' in request.GET:
  51. stats.strip_dirs()
  52. if 'prof_sort' in request.GET:
  53. # See # http://docs.python.org/2/library/profile.html#pstats.Stats.sort_stats
  54. # for the fields you can sort on.
  55. stats.sort_stats(*request.GET['prof_sort'].split(','))
  56. else:
  57. stats.sort_stats('time', 'calls')
  58. # Capture STDOUT temporarily
  59. old_stdout = sys.stdout
  60. out = StringIO()
  61. sys.stdout = out
  62. stats.print_stats()
  63. stats_str = out.getvalue()
  64. sys.stdout.close()
  65. sys.stdout = old_stdout
  66. # Print status within PRE block
  67. if response and response.content and stats_str:
  68. response.content = "<pre>" + stats_str + "</pre>"
  69. return response
  70. class ProfileMiddleware(BaseMiddleware):
  71. query_param = 'cprofile'
  72. def profiler(self):
  73. return cProfile.Profile()
  74. def stats(self):
  75. self.profile.dump_stats(self.tmpfile.name)
  76. return pstats.Stats(self.tmpfile.name)
  77. class HotshotMiddleware(BaseMiddleware):
  78. """
  79. Displays hotshot profiling for any view.
  80. http://yoursite.com/yourview/?prof
  81. Based on http://djangosnippets.org/snippets/186/
  82. """
  83. query_param = 'hotshot'
  84. def profiler(self):
  85. return hotshot.Profile(self.tmpfile.name)
  86. def stats(self):
  87. self.profile.close()
  88. return hotshot.stats.load(self.tmpfile.name)