##// END OF EJS Templates
profiling: Adding support for kcachegrind output format, using lsprofcalltree
Nicolas Dumazet -
r8024:9a1b86cf default
parent child Browse files
Show More
@@ -0,0 +1,90 b''
1 """
2 lsprofcalltree.py - lsprof output which is readable by kcachegrind
3
4 Authors:
5 * David Allouche <david <at> allouche.net>
6 * Jp Calderone & Itamar Shtull-Trauring
7 * Johan Dahlin
8
9 This software may be used and distributed according to the terms
10 of the GNU General Public License, incorporated herein by reference.
11 """
12
13 import optparse
14 import os
15 import sys
16
17 def label(code):
18 if isinstance(code, str):
19 return '~' + code # built-in functions ('~' sorts at the end)
20 else:
21 return '%s %s:%d' % (code.co_name,
22 code.co_filename,
23 code.co_firstlineno)
24
25 class KCacheGrind(object):
26 def __init__(self, profiler):
27 self.data = profiler.getstats()
28 self.out_file = None
29
30 def output(self, out_file):
31 self.out_file = out_file
32 print >> out_file, 'events: Ticks'
33 self._print_summary()
34 for entry in self.data:
35 self._entry(entry)
36
37 def _print_summary(self):
38 max_cost = 0
39 for entry in self.data:
40 totaltime = int(entry.totaltime * 1000)
41 max_cost = max(max_cost, totaltime)
42 print >> self.out_file, 'summary: %d' % (max_cost,)
43
44 def _entry(self, entry):
45 out_file = self.out_file
46
47 code = entry.code
48 #print >> out_file, 'ob=%s' % (code.co_filename,)
49 if isinstance(code, str):
50 print >> out_file, 'fi=~'
51 else:
52 print >> out_file, 'fi=%s' % (code.co_filename,)
53 print >> out_file, 'fn=%s' % (label(code),)
54
55 inlinetime = int(entry.inlinetime * 1000)
56 if isinstance(code, str):
57 print >> out_file, '0 ', inlinetime
58 else:
59 print >> out_file, '%d %d' % (code.co_firstlineno, inlinetime)
60
61 # recursive calls are counted in entry.calls
62 if entry.calls:
63 calls = entry.calls
64 else:
65 calls = []
66
67 if isinstance(code, str):
68 lineno = 0
69 else:
70 lineno = code.co_firstlineno
71
72 for subentry in calls:
73 self._subentry(lineno, subentry)
74 print >> out_file
75
76 def _subentry(self, lineno, subentry):
77 out_file = self.out_file
78 code = subentry.code
79 #print >> out_file, 'cob=%s' % (code.co_filename,)
80 print >> out_file, 'cfn=%s' % (label(code),)
81 if isinstance(code, str):
82 print >> out_file, 'cfi=~'
83 print >> out_file, 'calls=%d 0' % (subentry.callcount,)
84 else:
85 print >> out_file, 'cfi=%s' % (code.co_filename,)
86 print >> out_file, 'calls=%d %d' % (
87 subentry.callcount, code.co_firstlineno)
88
89 totaltime = int(subentry.totaltime * 1000)
90 print >> out_file, '%d %d' % (lineno, totaltime)
@@ -552,6 +552,10 b' profiling::'
552 Generate a profiling report.
552 Generate a profiling report.
553 When saving to a file, it should be noted that only the report is saved,
553 When saving to a file, it should be noted that only the report is saved,
554 and the profiling data is not kept.
554 and the profiling data is not kept.
555 kcachegrind;;
556 Format profiling data for kcachegrind use:
557 when saving to a file, the generated file can directly be loaded
558 into kcachegrind.
555 output;;
559 output;;
556 File path where profiling data or report should be saved.
560 File path where profiling data or report should be saved.
557 If the file exists, it is replaced.
561 If the file exists, it is replaced.
@@ -381,7 +381,7 b' def _runcommand(ui, options, cmd, cmdfun'
381 if options['profile']:
381 if options['profile']:
382 format = ui.config('profiling', 'format', default='text')
382 format = ui.config('profiling', 'format', default='text')
383
383
384 if not format in ['text']:
384 if not format in ['text', 'kcachegrind']:
385 ui.warn(_("unrecognized profiling format '%s'"
385 ui.warn(_("unrecognized profiling format '%s'"
386 " - Ignored\n") % format)
386 " - Ignored\n") % format)
387 format = 'text'
387 format = 'text'
@@ -407,9 +407,16 b' def _runcommand(ui, options, cmd, cmdfun'
407 return checkargs()
407 return checkargs()
408 finally:
408 finally:
409 p.disable()
409 p.disable()
410 stats = lsprof.Stats(p.getstats())
410
411 stats.sort()
411 if format == 'kcachegrind':
412 stats.pprint(top=10, file=ostream, climit=5)
412 import lsprofcalltree
413 calltree = lsprofcalltree.KCacheGrind(p)
414 calltree.output(ostream)
415 else:
416 # format == 'text'
417 stats = lsprof.Stats(p.getstats())
418 stats.sort()
419 stats.pprint(top=10, file=ostream, climit=5)
413
420
414 if output:
421 if output:
415 ostream.close()
422 ostream.close()
@@ -18,4 +18,15 b' if "$TESTDIR/hghave" -q lsprof; then'
18
18
19 hg --profile --config profiling.format=text st 2>&1 \
19 hg --profile --config profiling.format=text st 2>&1 \
20 | grep CallCount > /dev/null || echo --profile format=text failed
20 | grep CallCount > /dev/null || echo --profile format=text failed
21
22 echo "[profiling]" >> $HGRCPATH
23 echo "format=kcachegrind" >> $HGRCPATH
24
25 hg --profile st 2>../out || echo --profile format=kcachegrind failed
26 grep 'events: Ticks' < ../out > /dev/null || echo --profile output is wrong
27
28 hg --profile --config profiling.output=../out st 2>&1 \
29 || echo --profile format=kcachegrind + output to file failed
30 grep 'events: Ticks' < ../out > /dev/null \
31 || echo --profile output is wrong
21 fi
32 fi
General Comments 0
You need to be logged in to leave comments. Login now