Mercurial > public > mercurial-scm > hg
annotate mercurial/profiling.py @ 30317:3fd53cc1aad8
profiling: make statprof the default profiler (BC)
The statprof sampling profiler runs with significantly less overhead.
Its data is therefore more useful. Furthermore, its default output
shows the hotpath by default, which I've found to be way more useful
than the default profiler's function time table.
There is one behavioral regression with this change worth noting:
the statprof profiler currently doesn't profile individual hgweb
requests like lsprof does. This is because the current implementation
of statprof only profiles the thread that started profiling.
The ability for lsprof to profile individual hgweb requests is
relatively new and likely not widely used. Furthermore, I have plans
to modify statprof to support profiling multiple threads. I expect
that change to go through several iterations. I'm submitting this
patch first so there is more time to test statprof. Perfect is the
enemy of good.
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Fri, 04 Nov 2016 21:44:25 -0700 |
parents | faf1b8923da2 |
children | 189a1030affb |
rev | line source |
---|---|
29781
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
1 # profiling.py - profiling functions |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
2 # |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
3 # Copyright 2016 Gregory Szorc <gregory.szorc@gmail.com> |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
4 # |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
5 # This software may be used and distributed according to the terms of the |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
6 # GNU General Public License version 2 or any later version. |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
7 |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
8 from __future__ import absolute_import, print_function |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
9 |
29783
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29781
diff
changeset
|
10 import contextlib |
29781
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
11 import os |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
12 import sys |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
13 import time |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
14 |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
15 from .i18n import _ |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
16 from . import ( |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
17 error, |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
18 util, |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
19 ) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
20 |
29783
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29781
diff
changeset
|
21 @contextlib.contextmanager |
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29781
diff
changeset
|
22 def lsprofile(ui, fp): |
29781
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
23 format = ui.config('profiling', 'format', default='text') |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
24 field = ui.config('profiling', 'sort', default='inlinetime') |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
25 limit = ui.configint('profiling', 'limit', default=30) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
26 climit = ui.configint('profiling', 'nested', default=0) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
27 |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
28 if format not in ['text', 'kcachegrind']: |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
29 ui.warn(_("unrecognized profiling format '%s'" |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
30 " - Ignored\n") % format) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
31 format = 'text' |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
32 |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
33 try: |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
34 from . import lsprof |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
35 except ImportError: |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
36 raise error.Abort(_( |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
37 'lsprof not available - install from ' |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
38 'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/')) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
39 p = lsprof.Profiler() |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
40 p.enable(subcalls=True) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
41 try: |
29783
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29781
diff
changeset
|
42 yield |
29781
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
43 finally: |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
44 p.disable() |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
45 |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
46 if format == 'kcachegrind': |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
47 from . import lsprofcalltree |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
48 calltree = lsprofcalltree.KCacheGrind(p) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
49 calltree.output(fp) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
50 else: |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
51 # format == 'text' |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
52 stats = lsprof.Stats(p.getstats()) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
53 stats.sort(field) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
54 stats.pprint(limit=limit, file=fp, climit=climit) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
55 |
29783
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29781
diff
changeset
|
56 @contextlib.contextmanager |
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29781
diff
changeset
|
57 def flameprofile(ui, fp): |
29781
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
58 try: |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
59 from flamegraph import flamegraph |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
60 except ImportError: |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
61 raise error.Abort(_( |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
62 'flamegraph not available - install from ' |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
63 'https://github.com/evanhempel/python-flamegraph')) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
64 # developer config: profiling.freq |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
65 freq = ui.configint('profiling', 'freq', default=1000) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
66 filter_ = None |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
67 collapse_recursion = True |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
68 thread = flamegraph.ProfileThread(fp, 1.0 / freq, |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
69 filter_, collapse_recursion) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
70 start_time = time.clock() |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
71 try: |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
72 thread.start() |
29783
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29781
diff
changeset
|
73 yield |
29781
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
74 finally: |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
75 thread.stop() |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
76 thread.join() |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
77 print('Collected %d stack frames (%d unique) in %2.2f seconds.' % ( |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
78 time.clock() - start_time, thread.num_frames(), |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
79 thread.num_frames(unique=True))) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
80 |
29783
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29781
diff
changeset
|
81 @contextlib.contextmanager |
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29781
diff
changeset
|
82 def statprofile(ui, fp): |
30316
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29785
diff
changeset
|
83 from . import statprof |
29781
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
84 |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
85 freq = ui.configint('profiling', 'freq', default=1000) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
86 if freq > 0: |
29785
88d3c1ab03a7
profiling: don't error with statprof when profiling has already started
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29784
diff
changeset
|
87 # Cannot reset when profiler is already active. So silently no-op. |
88d3c1ab03a7
profiling: don't error with statprof when profiling has already started
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29784
diff
changeset
|
88 if statprof.state.profile_level == 0: |
88d3c1ab03a7
profiling: don't error with statprof when profiling has already started
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29784
diff
changeset
|
89 statprof.reset(freq) |
29781
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
90 else: |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
91 ui.warn(_("invalid sampling frequency '%s' - ignoring\n") % freq) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
92 |
30316
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29785
diff
changeset
|
93 statprof.start(mechanism='thread') |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29785
diff
changeset
|
94 |
29781
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
95 try: |
29783
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29781
diff
changeset
|
96 yield |
29781
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
97 finally: |
30316
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29785
diff
changeset
|
98 data = statprof.stop() |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29785
diff
changeset
|
99 |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29785
diff
changeset
|
100 profformat = ui.config('profiling', 'statformat', 'hotpath') |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29785
diff
changeset
|
101 |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29785
diff
changeset
|
102 formats = { |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29785
diff
changeset
|
103 'byline': statprof.DisplayFormats.ByLine, |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29785
diff
changeset
|
104 'bymethod': statprof.DisplayFormats.ByMethod, |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29785
diff
changeset
|
105 'hotpath': statprof.DisplayFormats.Hotpath, |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29785
diff
changeset
|
106 'json': statprof.DisplayFormats.Json, |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29785
diff
changeset
|
107 } |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29785
diff
changeset
|
108 |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29785
diff
changeset
|
109 if profformat in formats: |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29785
diff
changeset
|
110 displayformat = formats[profformat] |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29785
diff
changeset
|
111 else: |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29785
diff
changeset
|
112 ui.warn(_('unknown profiler output format: %s\n') % profformat) |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29785
diff
changeset
|
113 displayformat = statprof.DisplayFormats.Hotpath |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29785
diff
changeset
|
114 |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29785
diff
changeset
|
115 statprof.display(fp, data=data, format=displayformat) |
29781
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
116 |
29783
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29781
diff
changeset
|
117 @contextlib.contextmanager |
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29781
diff
changeset
|
118 def profile(ui): |
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29781
diff
changeset
|
119 """Start profiling. |
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29781
diff
changeset
|
120 |
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29781
diff
changeset
|
121 Profiling is active when the context manager is active. When the context |
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29781
diff
changeset
|
122 manager exits, profiling results will be written to the configured output. |
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29781
diff
changeset
|
123 """ |
29781
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
124 profiler = os.getenv('HGPROF') |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
125 if profiler is None: |
30317
3fd53cc1aad8
profiling: make statprof the default profiler (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30316
diff
changeset
|
126 profiler = ui.config('profiling', 'type', default='stat') |
29781
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
127 if profiler not in ('ls', 'stat', 'flame'): |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
128 ui.warn(_("unrecognized profiler '%s' - ignored\n") % profiler) |
30317
3fd53cc1aad8
profiling: make statprof the default profiler (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30316
diff
changeset
|
129 profiler = 'stat' |
29781
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
130 |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
131 output = ui.config('profiling', 'output') |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
132 |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
133 if output == 'blackbox': |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
134 fp = util.stringio() |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
135 elif output: |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
136 path = ui.expandpath(output) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
137 fp = open(path, 'wb') |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
138 else: |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
139 fp = sys.stderr |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
140 |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
141 try: |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
142 if profiler == 'ls': |
29783
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29781
diff
changeset
|
143 proffn = lsprofile |
29781
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
144 elif profiler == 'flame': |
29783
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29781
diff
changeset
|
145 proffn = flameprofile |
29781
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
146 else: |
29783
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29781
diff
changeset
|
147 proffn = statprofile |
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29781
diff
changeset
|
148 |
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29781
diff
changeset
|
149 with proffn(ui, fp): |
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29781
diff
changeset
|
150 yield |
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29781
diff
changeset
|
151 |
29781
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
152 finally: |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
153 if output: |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
154 if output == 'blackbox': |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
155 val = 'Profile:\n%s' % fp.getvalue() |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
156 # ui.log treats the input as a format string, |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
157 # so we need to escape any % signs. |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
158 val = val.replace('%', '%%') |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
159 ui.log('profile', val) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
160 fp.close() |
29784
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29783
diff
changeset
|
161 |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29783
diff
changeset
|
162 @contextlib.contextmanager |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29783
diff
changeset
|
163 def maybeprofile(ui): |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29783
diff
changeset
|
164 """Profile if enabled, else do nothing. |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29783
diff
changeset
|
165 |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29783
diff
changeset
|
166 This context manager can be used to optionally profile if profiling |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29783
diff
changeset
|
167 is enabled. Otherwise, it does nothing. |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29783
diff
changeset
|
168 |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29783
diff
changeset
|
169 The purpose of this context manager is to make calling code simpler: |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29783
diff
changeset
|
170 just use a single code path for calling into code you may want to profile |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29783
diff
changeset
|
171 and this function determines whether to start profiling. |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29783
diff
changeset
|
172 """ |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29783
diff
changeset
|
173 if ui.configbool('profiling', 'enabled'): |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29783
diff
changeset
|
174 with profile(ui): |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29783
diff
changeset
|
175 yield |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29783
diff
changeset
|
176 else: |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29783
diff
changeset
|
177 yield |