# Portions Copyright (c) Meta Platforms, Inc. and affiliates. # # This software may be used and distributed according to the terms of the # GNU General Public License version 2. # Copyright Olivia Mackall and others """ lsprofcalltree.py - lsprof output which is readable by kcachegrind Authors: * David Allouche 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. """ from __future__ import absolute_import, print_function def label(code): if isinstance(code, str): return "~" + code # built-in functions ('~' sorts at the end) else: return "%s %s:%d" % (code.co_name, code.co_filename, code.co_firstlineno) class KCacheGrind(object): def __init__(self, profiler): self.data = profiler.getstats() self.out_file = None def output(self, out_file): self.out_file = out_file print("events: Ticks", file=out_file) 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) print("summary: %d" % max_cost, file=self.out_file) def _entry(self, entry): out_file = self.out_file code = entry.code if isinstance(code, str): print("fi=~", file=out_file) else: print("fi=%s" % code.co_filename, file=out_file) print("fn=%s" % label(code), file=out_file) inlinetime = int(entry.inlinetime * 1000) if isinstance(code, str): print("0 ", inlinetime, file=out_file) else: print("%d %d" % (code.co_firstlineno, inlinetime), file=out_file) # 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) print(file=out_file) def _subentry(self, lineno, subentry): out_file = self.out_file code = subentry.code print("cfn=%s" % label(code), file=out_file) if isinstance(code, str): print("cfi=~", file=out_file) print("calls=%d 0" % subentry.callcount, file=out_file) else: print("cfi=%s" % code.co_filename, file=out_file) print( "calls=%d %d" % (subentry.callcount, code.co_firstlineno), file=out_file ) totaltime = int(subentry.totaltime * 1000) print("%d %d" % (lineno, totaltime), file=out_file)