lsprofcalltree.py
96 lines
| 2.7 KiB
| text/x-python
|
PythonLexer
/ mercurial / lsprofcalltree.py
Nicolas Dumazet
|
r8024 | """ | ||
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. | ||||
""" | ||||
Matt Harbison
|
r52756 | from __future__ import annotations | ||
Gregory Szorc
|
r27505 | |||
Augie Fackler
|
r43346 | from . import pycompat | ||
Gregory Szorc
|
r40231 | |||
Nicolas Dumazet
|
r8024 | def label(code): | ||
if isinstance(code, str): | ||||
Gregory Szorc
|
r40231 | # built-in functions ('~' sorts at the end) | ||
Augie Fackler
|
r43347 | return b'~' + pycompat.sysbytes(code) | ||
Nicolas Dumazet
|
r8024 | else: | ||
Augie Fackler
|
r43347 | return b'%s %s:%d' % ( | ||
Augie Fackler
|
r43346 | pycompat.sysbytes(code.co_name), | ||
pycompat.sysbytes(code.co_filename), | ||||
code.co_firstlineno, | ||||
) | ||||
Nicolas Dumazet
|
r8024 | |||
Gregory Szorc
|
r49801 | class KCacheGrind: | ||
Nicolas Dumazet
|
r8024 | def __init__(self, profiler): | ||
self.data = profiler.getstats() | ||||
self.out_file = None | ||||
def output(self, out_file): | ||||
self.out_file = out_file | ||||
Gregory Szorc
|
r40230 | out_file.write(b'events: Ticks\n') | ||
Nicolas Dumazet
|
r8024 | 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) | ||||
Gregory Szorc
|
r40230 | self.out_file.write(b'summary: %d\n' % max_cost) | ||
Nicolas Dumazet
|
r8024 | |||
def _entry(self, entry): | ||||
out_file = self.out_file | ||||
code = entry.code | ||||
if isinstance(code, str): | ||||
Gregory Szorc
|
r40230 | out_file.write(b'fi=~\n') | ||
Nicolas Dumazet
|
r8024 | else: | ||
Gregory Szorc
|
r40231 | out_file.write(b'fi=%s\n' % pycompat.sysbytes(code.co_filename)) | ||
Gregory Szorc
|
r40230 | |||
out_file.write(b'fn=%s\n' % label(code)) | ||||
Nicolas Dumazet
|
r8024 | |||
inlinetime = int(entry.inlinetime * 1000) | ||||
if isinstance(code, str): | ||||
Gregory Szorc
|
r40230 | out_file.write(b'0 %d\n' % inlinetime) | ||
Nicolas Dumazet
|
r8024 | else: | ||
Gregory Szorc
|
r40230 | out_file.write(b'%d %d\n' % (code.co_firstlineno, inlinetime)) | ||
Nicolas Dumazet
|
r8024 | |||
# 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) | ||||
Gregory Szorc
|
r40230 | |||
out_file.write(b'\n') | ||||
Nicolas Dumazet
|
r8024 | |||
def _subentry(self, lineno, subentry): | ||||
out_file = self.out_file | ||||
code = subentry.code | ||||
Gregory Szorc
|
r40230 | out_file.write(b'cfn=%s\n' % label(code)) | ||
Nicolas Dumazet
|
r8024 | if isinstance(code, str): | ||
Gregory Szorc
|
r40230 | out_file.write(b'cfi=~\n') | ||
out_file.write(b'calls=%d 0\n' % subentry.callcount) | ||||
Nicolas Dumazet
|
r8024 | else: | ||
Gregory Szorc
|
r40231 | out_file.write(b'cfi=%s\n' % pycompat.sysbytes(code.co_filename)) | ||
Augie Fackler
|
r43346 | out_file.write( | ||
b'calls=%d %d\n' % (subentry.callcount, code.co_firstlineno) | ||||
) | ||||
Nicolas Dumazet
|
r8024 | |||
totaltime = int(subentry.totaltime * 1000) | ||||
Gregory Szorc
|
r40230 | out_file.write(b'%d %d\n' % (lineno, totaltime)) | ||