~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/lsprof.py

  • Committer: Robert Collins
  • Date: 2007-07-04 08:08:13 UTC
  • mfrom: (2572 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2587.
  • Revision ID: robertc@robertcollins.net-20070704080813-wzebx0r88fvwj5rq
Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
# I made one modification to profile so that it returns a pair
4
4
# instead of just the Stats object
5
5
 
 
6
import cPickle
 
7
import os
6
8
import sys
7
9
import thread
8
10
import threading
104
106
        """Output profiling data in calltree format (for KCacheGrind)."""
105
107
        _CallTreeFilter(self.data).output(file)
106
108
 
 
109
    def save(self, filename, format=None):
 
110
        """Save profiling data to a file.
 
111
 
 
112
        :param filename: the name of the output file
 
113
        :param format: 'txt' for a text representation;
 
114
            'callgrind' for calltree format;
 
115
            otherwise a pickled Python object. A format of None indicates
 
116
            that the format to use is to be found from the extension of
 
117
            filename.
 
118
        """
 
119
        if format is None:
 
120
            ext = os.path.splitext(filename)[1]
 
121
            if len(ext) > 1:
 
122
                format = ext[1:]
 
123
        outfile = open(filename, 'wb')
 
124
        try:
 
125
            if format == "callgrind":
 
126
                self.calltree(outfile)
 
127
            elif format == "txt":
 
128
                self.pprint(file=outfile)
 
129
            else:
 
130
                self.freeze()
 
131
                cPickle.dump(self, outfile, 2)
 
132
        finally:
 
133
            outfile.close()
 
134
 
107
135
 
108
136
class _CallTreeFilter(object):
 
137
    """Converter of a Stats object to input suitable for KCacheGrind.
 
138
 
 
139
    This code is taken from http://ddaa.net/blog/python/lsprof-calltree
 
140
    with the changes made by J.P. Calderone and Itamar applied. Note that
 
141
    isinstance(code, str) needs to be used at times to determine if the code 
 
142
    object is actually an external code object (with a filename, etc.) or
 
143
    a Python built-in.
 
144
    """
109
145
 
110
146
    def __init__(self, data):
111
147
        self.data = data
130
166
        code = entry.code
131
167
        inlinetime = int(entry.inlinetime * 1000)
132
168
        #print >> out_file, 'ob=%s' % (code.co_filename,)
133
 
        print >> out_file, 'fi=%s' % (code.co_filename,)
 
169
        if isinstance(code, str):
 
170
            print >> out_file, 'fi=~'
 
171
        else:
 
172
            print >> out_file, 'fi=%s' % (code.co_filename,)
134
173
        print >> out_file, 'fn=%s' % (label(code, True),)
135
 
        print >> out_file, '%d %d' % (code.co_firstlineno, inlinetime)
 
174
        if isinstance(code, str):
 
175
            print >> out_file, '0 ', inlinetime
 
176
        else:
 
177
            print >> out_file, '%d %d' % (code.co_firstlineno, inlinetime)
136
178
        # recursive calls are counted in entry.calls
137
179
        if entry.calls:
138
180
            calls = entry.calls
139
181
        else:
140
182
            calls = []
 
183
        if isinstance(code, str):
 
184
            lineno = 0
 
185
        else:
 
186
            lineno = code.co_firstlineno
141
187
        for subentry in calls:
142
 
            self._subentry(code.co_firstlineno, subentry)
 
188
            self._subentry(lineno, subentry)
143
189
        print >> out_file
144
190
 
145
191
    def _subentry(self, lineno, subentry):
148
194
        totaltime = int(subentry.totaltime * 1000)
149
195
        #print >> out_file, 'cob=%s' % (code.co_filename,)
150
196
        print >> out_file, 'cfn=%s' % (label(code, True),)
151
 
        print >> out_file, 'cfi=%s' % (code.co_filename,)
152
 
        print >> out_file, 'calls=%d %d' % (
153
 
            subentry.callcount, code.co_firstlineno)
 
197
        if isinstance(code, str):
 
198
            print >> out_file, 'cfi=~'
 
199
            print >> out_file, 'calls=%d 0' % (subentry.callcount,)
 
200
        else:
 
201
            print >> out_file, 'cfi=%s' % (code.co_filename,)
 
202
            print >> out_file, 'calls=%d %d' % (
 
203
                subentry.callcount, code.co_firstlineno)
154
204
        print >> out_file, '%d %d' % (lineno, totaltime)
155
205
 
156
 
 
157
206
_fn2mod = {}
158
207
 
159
208
def label(code, calltree=False):