mercurial/lsprofcalltree.py
changeset 8024 9a1b86cfd29e
child 8390 beae42f3d93b
equal deleted inserted replaced
8023:fd9debb3ea1b 8024:9a1b86cfd29e
       
     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)