--- a/doc/hgrc.5.txt Thu Apr 02 16:01:30 2009 +0900
+++ b/doc/hgrc.5.txt Wed Apr 08 14:20:57 2009 +0200
@@ -552,6 +552,10 @@
Generate a profiling report.
When saving to a file, it should be noted that only the report is saved,
and the profiling data is not kept.
+ kcachegrind;;
+ Format profiling data for kcachegrind use:
+ when saving to a file, the generated file can directly be loaded
+ into kcachegrind.
output;;
File path where profiling data or report should be saved.
If the file exists, it is replaced.
--- a/mercurial/dispatch.py Thu Apr 02 16:01:30 2009 +0900
+++ b/mercurial/dispatch.py Wed Apr 08 14:20:57 2009 +0200
@@ -381,7 +381,7 @@
if options['profile']:
format = ui.config('profiling', 'format', default='text')
- if not format in ['text']:
+ if not format in ['text', 'kcachegrind']:
ui.warn(_("unrecognized profiling format '%s'"
" - Ignored\n") % format)
format = 'text'
@@ -407,9 +407,16 @@
return checkargs()
finally:
p.disable()
- stats = lsprof.Stats(p.getstats())
- stats.sort()
- stats.pprint(top=10, file=ostream, climit=5)
+
+ if format == 'kcachegrind':
+ import lsprofcalltree
+ calltree = lsprofcalltree.KCacheGrind(p)
+ calltree.output(ostream)
+ else:
+ # format == 'text'
+ stats = lsprof.Stats(p.getstats())
+ stats.sort()
+ stats.pprint(top=10, file=ostream, climit=5)
if output:
ostream.close()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial/lsprofcalltree.py Wed Apr 08 14:20:57 2009 +0200
@@ -0,0 +1,90 @@
+"""
+lsprofcalltree.py - lsprof output which is readable by kcachegrind
+
+Authors:
+ * David Allouche <david <at> allouche.net>
+ * Jp Calderone & Itamar Shtull-Trauring
+ * Johan Dahlin
+
+This software may be used and distributed according to the terms
+of the GNU General Public License, incorporated herein by reference.
+"""
+
+import optparse
+import os
+import sys
+
+def label(code):
+ if isinstance(code, str):
+ return '~' + code # built-in functions ('~' sorts at the end)
+ else:
+ return '%s %s:%d' % (code.co_name,
+ code.co_filename,
+ code.co_firstlineno)
+
+class KCacheGrind(object):
+ def __init__(self, profiler):
+ self.data = profiler.getstats()
+ self.out_file = None
+
+ def output(self, out_file):
+ self.out_file = out_file
+ print >> out_file, 'events: Ticks'
+ self._print_summary()
+ for entry in self.data:
+ self._entry(entry)
+
+ def _print_summary(self):
+ max_cost = 0
+ for entry in self.data:
+ totaltime = int(entry.totaltime * 1000)
+ max_cost = max(max_cost, totaltime)
+ print >> self.out_file, 'summary: %d' % (max_cost,)
+
+ def _entry(self, entry):
+ out_file = self.out_file
+
+ code = entry.code
+ #print >> out_file, 'ob=%s' % (code.co_filename,)
+ if isinstance(code, str):
+ print >> out_file, 'fi=~'
+ else:
+ print >> out_file, 'fi=%s' % (code.co_filename,)
+ print >> out_file, 'fn=%s' % (label(code),)
+
+ inlinetime = int(entry.inlinetime * 1000)
+ if isinstance(code, str):
+ print >> out_file, '0 ', inlinetime
+ else:
+ print >> out_file, '%d %d' % (code.co_firstlineno, inlinetime)
+
+ # recursive calls are counted in entry.calls
+ if entry.calls:
+ calls = entry.calls
+ else:
+ calls = []
+
+ if isinstance(code, str):
+ lineno = 0
+ else:
+ lineno = code.co_firstlineno
+
+ for subentry in calls:
+ self._subentry(lineno, subentry)
+ print >> out_file
+
+ def _subentry(self, lineno, subentry):
+ out_file = self.out_file
+ code = subentry.code
+ #print >> out_file, 'cob=%s' % (code.co_filename,)
+ print >> out_file, 'cfn=%s' % (label(code),)
+ if isinstance(code, str):
+ print >> out_file, 'cfi=~'
+ print >> out_file, 'calls=%d 0' % (subentry.callcount,)
+ else:
+ print >> out_file, 'cfi=%s' % (code.co_filename,)
+ print >> out_file, 'calls=%d %d' % (
+ subentry.callcount, code.co_firstlineno)
+
+ totaltime = int(subentry.totaltime * 1000)
+ print >> out_file, '%d %d' % (lineno, totaltime)
--- a/tests/test-profile Thu Apr 02 16:01:30 2009 +0900
+++ b/tests/test-profile Wed Apr 08 14:20:57 2009 +0200
@@ -18,4 +18,15 @@
hg --profile --config profiling.format=text st 2>&1 \
| grep CallCount > /dev/null || echo --profile format=text failed
+
+ echo "[profiling]" >> $HGRCPATH
+ echo "format=kcachegrind" >> $HGRCPATH
+
+ hg --profile st 2>../out || echo --profile format=kcachegrind failed
+ grep 'events: Ticks' < ../out > /dev/null || echo --profile output is wrong
+
+ hg --profile --config profiling.output=../out st 2>&1 \
+ || echo --profile format=kcachegrind + output to file failed
+ grep 'events: Ticks' < ../out > /dev/null \
+ || echo --profile output is wrong
fi