|
1 """ Tools for profiling. |
|
2 |
|
3 See :ref:`profiling`.""" |
|
4 from __future__ import print_function |
|
5 |
|
6 import cProfile |
|
7 import itertools |
|
8 |
|
9 from pyramid.view import view_config |
|
10 |
|
11 |
|
12 @view_config(route_name='profile_ping') |
|
13 def ping(request): |
|
14 """ View that handle '/_profile/ping' |
|
15 |
|
16 It simply reply 'ping', without requiring connection to the repository. |
|
17 It is a useful as a comparison point to evaluate the actual overhead of |
|
18 more costly views. |
|
19 """ |
|
20 request.response.text = u'pong' |
|
21 return request.response |
|
22 |
|
23 |
|
24 @view_config(route_name='profile_cnx') |
|
25 def cnx(request): |
|
26 """ View that handle '/_profile/cnx' |
|
27 |
|
28 Same as :func:`ping`, but it first ask for a connection to the repository. |
|
29 Useful to evaluate the overhead of opening a connection. |
|
30 """ |
|
31 request.cw_cnx |
|
32 request.response.text = u'pong' |
|
33 return request.response |
|
34 |
|
35 |
|
36 def wsgi_profile(app, filename='program.prof', dump_every=50): |
|
37 """ A WSGI middleware for profiling |
|
38 |
|
39 It enable the profiler before passing the request to the underlying |
|
40 application, and disable it just after. |
|
41 |
|
42 The stats will be dumped after ``dump_every`` requests |
|
43 |
|
44 :param filename: The filename to dump the stats to. |
|
45 :param dump_every: Number of requests after which to dump the stats. |
|
46 """ |
|
47 |
|
48 profile = cProfile.Profile() |
|
49 |
|
50 counter = itertools.count(1) |
|
51 |
|
52 def application(environ, start_response): |
|
53 profile.enable() |
|
54 try: |
|
55 return app(environ, start_response) |
|
56 finally: |
|
57 profile.disable() |
|
58 if not counter.next() % dump_every: |
|
59 print("Dump profile stats to %s" % filename) |
|
60 profile.create_stats() |
|
61 profile.dump_stats(filename) |
|
62 |
|
63 return application |