eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/mercurial/lsprof.py
changeset 69 c6bca38c1cbf
equal deleted inserted replaced
68:5ff1fc726848 69:c6bca38c1cbf
       
     1 import sys
       
     2 from _lsprof import Profiler, profiler_entry
       
     3 
       
     4 __all__ = ['profile', 'Stats']
       
     5 
       
     6 def profile(f, *args, **kwds):
       
     7     """XXX docstring"""
       
     8     p = Profiler()
       
     9     p.enable(subcalls=True, builtins=True)
       
    10     try:
       
    11         f(*args, **kwds)
       
    12     finally:
       
    13         p.disable()
       
    14     return Stats(p.getstats())
       
    15 
       
    16 
       
    17 class Stats(object):
       
    18     """XXX docstring"""
       
    19 
       
    20     def __init__(self, data):
       
    21         self.data = data
       
    22 
       
    23     def sort(self, crit="inlinetime"):
       
    24         """XXX docstring"""
       
    25         if crit not in profiler_entry.__dict__:
       
    26             raise ValueError("Can't sort by %s" % crit)
       
    27         self.data.sort(key=lambda x: getattr(x, crit), reverse=True)
       
    28         for e in self.data:
       
    29             if e.calls:
       
    30                 e.calls.sort(key=lambda x: getattr(x, crit), reverse=True)
       
    31 
       
    32     def pprint(self, top=None, file=None, limit=None, climit=None):
       
    33         """XXX docstring"""
       
    34         if file is None:
       
    35             file = sys.stdout
       
    36         d = self.data
       
    37         if top is not None:
       
    38             d = d[:top]
       
    39         cols = "% 12s %12s %11.4f %11.4f   %s\n"
       
    40         hcols = "% 12s %12s %12s %12s %s\n"
       
    41         file.write(hcols % ("CallCount", "Recursive", "Total(ms)",
       
    42                             "Inline(ms)", "module:lineno(function)"))
       
    43         count = 0
       
    44         for e in d:
       
    45             file.write(cols % (e.callcount, e.reccallcount, e.totaltime,
       
    46                                e.inlinetime, label(e.code)))
       
    47             count += 1
       
    48             if limit is not None and count == limit:
       
    49                 return
       
    50             ccount = 0
       
    51             if e.calls:
       
    52                 for se in e.calls:
       
    53                     file.write(cols % ("+%s" % se.callcount, se.reccallcount,
       
    54                                        se.totaltime, se.inlinetime,
       
    55                                        "+%s" % label(se.code)))
       
    56                     count += 1
       
    57                     ccount += 1
       
    58                     if limit is not None and count == limit:
       
    59                         return
       
    60                     if climit is not None and ccount == climit:
       
    61                         break
       
    62 
       
    63     def freeze(self):
       
    64         """Replace all references to code objects with string
       
    65         descriptions; this makes it possible to pickle the instance."""
       
    66 
       
    67         # this code is probably rather ickier than it needs to be!
       
    68         for i in range(len(self.data)):
       
    69             e = self.data[i]
       
    70             if not isinstance(e.code, str):
       
    71                 self.data[i] = type(e)((label(e.code),) + e[1:])
       
    72             if e.calls:
       
    73                 for j in range(len(e.calls)):
       
    74                     se = e.calls[j]
       
    75                     if not isinstance(se.code, str):
       
    76                         e.calls[j] = type(se)((label(se.code),) + se[1:])
       
    77 
       
    78 _fn2mod = {}
       
    79 
       
    80 def label(code):
       
    81     if isinstance(code, str):
       
    82         return code
       
    83     try:
       
    84         mname = _fn2mod[code.co_filename]
       
    85     except KeyError:
       
    86         for k, v in list(sys.modules.iteritems()):
       
    87             if v is None:
       
    88                 continue
       
    89             if not hasattr(v, '__file__'):
       
    90                 continue
       
    91             if not isinstance(v.__file__, str):
       
    92                 continue
       
    93             if v.__file__.startswith(code.co_filename):
       
    94                 mname = _fn2mod[code.co_filename] = k
       
    95                 break
       
    96         else:
       
    97             mname = _fn2mod[code.co_filename] = '<%s>' % code.co_filename
       
    98 
       
    99     return '%s:%d(%s)' % (mname, code.co_firstlineno, code.co_name)
       
   100 
       
   101 
       
   102 if __name__ == '__main__':
       
   103     import os
       
   104     sys.argv = sys.argv[1:]
       
   105     if not sys.argv:
       
   106         print >> sys.stderr, "usage: lsprof.py <script> <arguments...>"
       
   107         sys.exit(2)
       
   108     sys.path.insert(0, os.path.abspath(os.path.dirname(sys.argv[0])))
       
   109     stats = profile(execfile, sys.argv[0], globals(), locals())
       
   110     stats.sort()
       
   111     stats.pprint()