"""Profiler tools for CherryPy. CherryPy users ============== You can profile any of your pages as follows:: from cherrypy.lib import profiler class Root: p = profiler.Profiler("/path/to/profile/dir") @cherrypy.expose def index(self): self.p.run(self._index) def _index(self): return "Hello, world!" cherrypy.tree.mount(Root()) You can also turn on profiling for all requests using the ``make_app`` function as WSGI middleware. CherryPy developers =================== This module can be used whenever you make changes to CherryPy, to get a quick sanity-check on overall CP performance. Use the ``--profile`` flag when running the test suite. Then, use the ``serve()`` function to browse the results in a web browser. If you run this module from the command line, it will call ``serve()`` for you. """ import io import os import os.path import sys import warnings import cherrypy try: import profile import pstats def new_func_strip_path(func_name): """Make profiler output more readable by adding `__init__` modules' parents """ filename, line, name = func_name if filename.endswith('__init__.py'): return os.path.basename(filename[:-12]) + filename[-12:], line, name return os.path.basename(filename), line, name pstats.func_strip_path = new_func_strip_path except ImportError: profile = None pstats = None _count = 0 class Profiler(object): def __init__(self, path=None): if not path: path = os.path.join(os.path.dirname(__file__), 'profile') self.path = path if not os.path.exists(path): os.makedirs(path) def run(self, func, *args, **params): """Dump profile data into self.path.""" global _count c = _count = _count + 1 path = os.path.join(self.path, 'cp_%04d.prof' % c) prof = profile.Profile() result = prof.runcall(func, *args, **params) prof.dump_stats(path) return result def statfiles(self): """:rtype: list of available profiles. """ return [f for f in os.listdir(self.path) if f.startswith('cp_') and f.endswith('.prof')] def stats(self, filename, sortby='cumulative'): """:rtype stats(index): output of print_stats() for the given profile. """ sio = io.StringIO() if sys.version_info >= (2, 5): s = pstats.Stats(os.path.join(self.path, filename), stream=sio) s.strip_dirs() s.sort_stats(sortby) s.print_stats() else: # pstats.Stats before Python 2.5 didn't take a 'stream' arg, # but just printed to stdout. So re-route stdout. s = pstats.Stats(os.path.join(self.path, filename)) s.strip_dirs() s.sort_stats(sortby) oldout = sys.stdout try: sys.stdout = sio s.print_stats() finally: sys.stdout = oldout response = sio.getvalue() sio.close() return response @cherrypy.expose def index(self): return """
Click on one of the runs below to see profiling data.
' runs = self.statfiles() runs.sort() for i in runs: yield "%s