Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(92)

Side by Side Diff: third_party/cherrypy/lib/profiler.py

Issue 9368042: Add CherryPy to third_party. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build/
Patch Set: '' Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « third_party/cherrypy/lib/jsontools.py ('k') | third_party/cherrypy/lib/reprconf.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 """Profiler tools for CherryPy.
2
3 CherryPy users
4 ==============
5
6 You can profile any of your pages as follows::
7
8 from cherrypy.lib import profiler
9
10 class Root:
11 p = profile.Profiler("/path/to/profile/dir")
12
13 def index(self):
14 self.p.run(self._index)
15 index.exposed = True
16
17 def _index(self):
18 return "Hello, world!"
19
20 cherrypy.tree.mount(Root())
21
22 You can also turn on profiling for all requests
23 using the ``make_app`` function as WSGI middleware.
24
25 CherryPy developers
26 ===================
27
28 This module can be used whenever you make changes to CherryPy,
29 to get a quick sanity-check on overall CP performance. Use the
30 ``--profile`` flag when running the test suite. Then, use the ``serve()``
31 function to browse the results in a web browser. If you run this
32 module from the command line, it will call ``serve()`` for you.
33
34 """
35
36
37 def new_func_strip_path(func_name):
38 """Make profiler output more readable by adding ``__init__`` modules' parent s"""
39 filename, line, name = func_name
40 if filename.endswith("__init__.py"):
41 return os.path.basename(filename[:-12]) + filename[-12:], line, name
42 return os.path.basename(filename), line, name
43
44 try:
45 import profile
46 import pstats
47 pstats.func_strip_path = new_func_strip_path
48 except ImportError:
49 profile = None
50 pstats = None
51
52 import os, os.path
53 import sys
54 import warnings
55
56 from cherrypy._cpcompat import BytesIO
57
58 _count = 0
59
60 class Profiler(object):
61
62 def __init__(self, path=None):
63 if not path:
64 path = os.path.join(os.path.dirname(__file__), "profile")
65 self.path = path
66 if not os.path.exists(path):
67 os.makedirs(path)
68
69 def run(self, func, *args, **params):
70 """Dump profile data into self.path."""
71 global _count
72 c = _count = _count + 1
73 path = os.path.join(self.path, "cp_%04d.prof" % c)
74 prof = profile.Profile()
75 result = prof.runcall(func, *args, **params)
76 prof.dump_stats(path)
77 return result
78
79 def statfiles(self):
80 """:rtype: list of available profiles.
81 """
82 return [f for f in os.listdir(self.path)
83 if f.startswith("cp_") and f.endswith(".prof")]
84
85 def stats(self, filename, sortby='cumulative'):
86 """:rtype stats(index): output of print_stats() for the given profile.
87 """
88 sio = BytesIO()
89 if sys.version_info >= (2, 5):
90 s = pstats.Stats(os.path.join(self.path, filename), stream=sio)
91 s.strip_dirs()
92 s.sort_stats(sortby)
93 s.print_stats()
94 else:
95 # pstats.Stats before Python 2.5 didn't take a 'stream' arg,
96 # but just printed to stdout. So re-route stdout.
97 s = pstats.Stats(os.path.join(self.path, filename))
98 s.strip_dirs()
99 s.sort_stats(sortby)
100 oldout = sys.stdout
101 try:
102 sys.stdout = sio
103 s.print_stats()
104 finally:
105 sys.stdout = oldout
106 response = sio.getvalue()
107 sio.close()
108 return response
109
110 def index(self):
111 return """<html>
112 <head><title>CherryPy profile data</title></head>
113 <frameset cols='200, 1*'>
114 <frame src='menu' />
115 <frame name='main' src='' />
116 </frameset>
117 </html>
118 """
119 index.exposed = True
120
121 def menu(self):
122 yield "<h2>Profiling runs</h2>"
123 yield "<p>Click on one of the runs below to see profiling data.</p>"
124 runs = self.statfiles()
125 runs.sort()
126 for i in runs:
127 yield "<a href='report?filename=%s' target='main'>%s</a><br />" % (i , i)
128 menu.exposed = True
129
130 def report(self, filename):
131 import cherrypy
132 cherrypy.response.headers['Content-Type'] = 'text/plain'
133 return self.stats(filename)
134 report.exposed = True
135
136
137 class ProfileAggregator(Profiler):
138
139 def __init__(self, path=None):
140 Profiler.__init__(self, path)
141 global _count
142 self.count = _count = _count + 1
143 self.profiler = profile.Profile()
144
145 def run(self, func, *args):
146 path = os.path.join(self.path, "cp_%04d.prof" % self.count)
147 result = self.profiler.runcall(func, *args)
148 self.profiler.dump_stats(path)
149 return result
150
151
152 class make_app:
153 def __init__(self, nextapp, path=None, aggregate=False):
154 """Make a WSGI middleware app which wraps 'nextapp' with profiling.
155
156 nextapp
157 the WSGI application to wrap, usually an instance of
158 cherrypy.Application.
159
160 path
161 where to dump the profiling output.
162
163 aggregate
164 if True, profile data for all HTTP requests will go in
165 a single file. If False (the default), each HTTP request will
166 dump its profile data into a separate file.
167
168 """
169 if profile is None or pstats is None:
170 msg = ("Your installation of Python does not have a profile module. "
171 "If you're on Debian, try `sudo apt-get install python-profil er`. "
172 "See http://www.cherrypy.org/wiki/ProfilingOnDebian for detai ls.")
173 warnings.warn(msg)
174
175 self.nextapp = nextapp
176 self.aggregate = aggregate
177 if aggregate:
178 self.profiler = ProfileAggregator(path)
179 else:
180 self.profiler = Profiler(path)
181
182 def __call__(self, environ, start_response):
183 def gather():
184 result = []
185 for line in self.nextapp(environ, start_response):
186 result.append(line)
187 return result
188 return self.profiler.run(gather)
189
190
191 def serve(path=None, port=8080):
192 if profile is None or pstats is None:
193 msg = ("Your installation of Python does not have a profile module. "
194 "If you're on Debian, try `sudo apt-get install python-profiler`. "
195 "See http://www.cherrypy.org/wiki/ProfilingOnDebian for details." )
196 warnings.warn(msg)
197
198 import cherrypy
199 cherrypy.config.update({'server.socket_port': int(port),
200 'server.thread_pool': 10,
201 'environment': "production",
202 })
203 cherrypy.quickstart(Profiler(path))
204
205
206 if __name__ == "__main__":
207 serve(*tuple(sys.argv[1:]))
208
OLDNEW
« no previous file with comments | « third_party/cherrypy/lib/jsontools.py ('k') | third_party/cherrypy/lib/reprconf.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698