[PATCH 1 of 1] Adding support for kcachegrind, using lsprofcalltree

Nicolas Dumazet nicdumz at gmail.com
Mon Mar 23 12:36:28 CDT 2009


# HG changeset patch
# User Nicolas Dumazet <nicdumz.commits at gmail.com>
# Date 1237829437 -32400
# Node ID a4e5223240a610818c2a0fae70e53d69e0292504
# Parent  c63c30ae9e39229ff3cbb2f452ef11a009a363f2
Adding support for kcachegrind, using lsprofcalltree

diff -r c63c30ae9e39 -r a4e5223240a6 mercurial/commands.py
--- a/mercurial/commands.py	Mon Mar 23 15:32:29 2009 +0100
+++ b/mercurial/commands.py	Tue Mar 24 02:30:37 2009 +0900
@@ -2974,6 +2974,8 @@
     ('', 'debugger', None, _('start debugger')),
     ('', 'encoding', util._encoding, _('set the charset encoding')),
     ('', 'encodingmode', util._encodingmode, _('set the charset encoding mode')),
+    ('', 'kcachegrind', '',
+    _('output kcachegrind execution profile to specified file')),
     ('', 'lsprof', None, _('print improved command execution profile')),
     ('', 'traceback', None, _('print traceback on exception')),
     ('', 'time', None, _('time how long the command takes')),
diff -r c63c30ae9e39 -r a4e5223240a6 mercurial/dispatch.py
--- a/mercurial/dispatch.py	Mon Mar 23 15:32:29 2009 +0100
+++ b/mercurial/dispatch.py	Tue Mar 24 02:30:37 2009 +0900
@@ -397,7 +397,7 @@
             stats.strip_dirs()
             stats.sort_stats('time', 'calls')
             stats.print_stats(40)
-    elif options['lsprof']:
+    elif options['kcachegrind'] or options['lsprof']:
         try:
             from mercurial import lsprof
         except ImportError:
@@ -410,8 +410,21 @@
             return checkargs()
         finally:
             p.disable()
-            stats = lsprof.Stats(p.getstats())
-            stats.sort()
-            stats.pprint(top=10, file=sys.stderr, climit=5)
+            if options['kcachegrind']:
+                import lsprofcalltree
+                calltree = lsprofcalltree.KCacheGrind(p)
+
+                path = options['kcachegrind']
+                path = os.path.expanduser(path)
+                path = ui.expandpath(path)
+
+                f = open(path, 'w+')        
+                calltree.output(f)
+                f.close()
+            else:
+                # lsprof handling
+                stats = lsprof.Stats(p.getstats())
+                stats.sort()
+                stats.pprint(top=10, file=sys.stderr, climit=5)
     else:
         return checkargs()
diff -r c63c30ae9e39 -r a4e5223240a6 mercurial/lsprofcalltree.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial/lsprofcalltree.py	Tue Mar 24 02:30:37 2009 +0900
@@ -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)
diff -r c63c30ae9e39 -r a4e5223240a6 tests/test-debugcomplete.out
--- a/tests/test-debugcomplete.out	Mon Mar 23 15:32:29 2009 +0100
+++ b/tests/test-debugcomplete.out	Tue Mar 24 02:30:37 2009 +0900
@@ -97,6 +97,7 @@
 --encoding
 --encodingmode
 --help
+--kcachegrind
 --lsprof
 --noninteractive
 --profile
@@ -127,6 +128,7 @@
 --errorlog
 --help
 --ipv6
+--kcachegrind
 --lsprof
 --name
 --noninteractive
diff -r c63c30ae9e39 -r a4e5223240a6 tests/test-extension.out
--- a/tests/test-extension.out	Mon Mar 23 15:32:29 2009 +0100
+++ b/tests/test-extension.out	Tue Mar 24 02:30:37 2009 +0900
@@ -48,6 +48,7 @@
     --debugger        start debugger
     --encoding        set the charset encoding (default: ascii)
     --encodingmode    set the charset encoding mode (default: strict)
+    --kcachegrind     output kcachegrind execution profile to specified file
     --lsprof          print improved command execution profile
     --traceback       print traceback on exception
     --time            time how long the command takes


More information about the Mercurial-devel mailing list