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.

profiling.py 2.8KB

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