106
104
"""Output profiling data in calltree format (for KCacheGrind)."""
107
105
_CallTreeFilter(self.data).output(file)
109
def save(self, filename, format=None):
110
"""Save profiling data to a file.
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 filename. If
117
the name starts with callgrind.out, callgrind format is used
118
otherwise the format is given by the filename extension.
121
if filename.startswith('callgrind.out'):
124
ext = os.path.splitext(filename)[1]
127
outfile = open(filename, 'wb')
129
if format == "callgrind":
130
self.calltree(outfile)
131
elif format == "txt":
132
self.pprint(file=outfile)
135
cPickle.dump(self, outfile, 2)
140
108
class _CallTreeFilter(object):
141
"""Converter of a Stats object to input suitable for KCacheGrind.
143
This code is taken from http://ddaa.net/blog/python/lsprof-calltree
144
with the changes made by J.P. Calderone and Itamar applied. Note that
145
isinstance(code, str) needs to be used at times to determine if the code
146
object is actually an external code object (with a filename, etc.) or
150
110
def __init__(self, data):
170
130
code = entry.code
171
131
inlinetime = int(entry.inlinetime * 1000)
172
132
#print >> out_file, 'ob=%s' % (code.co_filename,)
173
if isinstance(code, str):
174
print >> out_file, 'fi=~'
176
print >> out_file, 'fi=%s' % (code.co_filename,)
133
print >> out_file, 'fi=%s' % (code.co_filename,)
177
134
print >> out_file, 'fn=%s' % (label(code, True),)
178
if isinstance(code, str):
179
print >> out_file, '0 ', inlinetime
181
print >> out_file, '%d %d' % (code.co_firstlineno, inlinetime)
135
print >> out_file, '%d %d' % (code.co_firstlineno, inlinetime)
182
136
# recursive calls are counted in entry.calls
184
138
calls = entry.calls
187
if isinstance(code, str):
190
lineno = code.co_firstlineno
191
141
for subentry in calls:
192
self._subentry(lineno, subentry)
142
self._subentry(code.co_firstlineno, subentry)
193
143
print >> out_file
195
145
def _subentry(self, lineno, subentry):
198
148
totaltime = int(subentry.totaltime * 1000)
199
149
#print >> out_file, 'cob=%s' % (code.co_filename,)
200
150
print >> out_file, 'cfn=%s' % (label(code, True),)
201
if isinstance(code, str):
202
print >> out_file, 'cfi=~'
203
print >> out_file, 'calls=%d 0' % (subentry.callcount,)
205
print >> out_file, 'cfi=%s' % (code.co_filename,)
206
print >> out_file, 'calls=%d %d' % (
207
subentry.callcount, code.co_firstlineno)
151
print >> out_file, 'cfi=%s' % (code.co_filename,)
152
print >> out_file, 'calls=%d %d' % (
153
subentry.callcount, code.co_firstlineno)
208
154
print >> out_file, '%d %d' % (lineno, totaltime)
212
159
def label(code, calltree=False):