import sys import tempfile import hotshot import hotshot.stats from cStringIO import StringIO import cProfile import pstats def profile_this(fn): def profiled_fn(*args, **kwargs): filepath = "/tmp/%s.profile" % fn.__name__ prof = cProfile.Profile() ret = prof.runcall(fn, *args, **kwargs) print "Writing to %s" % filepath prof.dump_stats(filepath) print "Printing stats" stats = pstats.Stats(filepath) stats.sort_stats('cumulative') stats.print_stats() return ret return profiled_fn class BaseMiddleware(object): query_param = None def show_profile(self, request): return self.query_param in request.GET def process_request(self, request): if self.show_profile(request): if 'prof_file' in request.GET: # It's sometimes useful to generate a file of output that can # converted for use with kcachegrind. To convert this file, # use: # # pyprof2calltree -o /tmp/callgrind.stats -i /tmp/out.stats # # then open the file in kcachegrind. self.tmpfile = open('/tmp/out.stats', 'w') else: self.tmpfile = tempfile.NamedTemporaryFile() self.profile = self.profiler() def profiler(self): return None def process_view(self, request, callback, callback_args, callback_kwargs): # We profile the view call - note that this misses the rest of Django's # request processing (eg middleware etc) if self.show_profile(request): return self.profile.runcall( callback, request, *callback_args, **callback_kwargs) def process_response(self, request, response): if self.show_profile(request): stats = self.stats() if 'prof_strip' in request.GET: stats.strip_dirs() if 'prof_sort' in request.GET: # See # http://docs.python.org/2/library/profile.html#pstats.Stats.sort_stats # for the fields you can sort on. stats.sort_stats(*request.GET['prof_sort'].split(',')) else: stats.sort_stats('time', 'calls') # Capture STDOUT temporarily old_stdout = sys.stdout out = StringIO() sys.stdout = out stats.print_stats() stats_str = out.getvalue() sys.stdout.close() sys.stdout = old_stdout # Print status within PRE block if response and response.content and stats_str: response.content = "
" + stats_str + "
" return response class ProfileMiddleware(BaseMiddleware): query_param = 'cprofile' def profiler(self): return cProfile.Profile() def stats(self): self.profile.dump_stats(self.tmpfile.name) return pstats.Stats(self.tmpfile.name) class HotshotMiddleware(BaseMiddleware): """ Displays hotshot profiling for any view. http://yoursite.com/yourview/?prof Based on http://djangosnippets.org/snippets/186/ """ query_param = 'hotshot' def profiler(self): return hotshot.Profile(self.tmpfile.name) def stats(self): self.profile.close() return hotshot.stats.load(self.tmpfile.name)