62 lines
1.8 KiB
Python
62 lines
1.8 KiB
Python
|
|
from AddrResolver import AddrResolver
|
||
|
|
|
||
|
|
|
||
|
|
class Profiler:
|
||
|
|
def __init__(self, filename):
|
||
|
|
self.addr_resolver = AddrResolver(filename)
|
||
|
|
|
||
|
|
def resolver(self):
|
||
|
|
return self.addr_resolver
|
||
|
|
|
||
|
|
|
||
|
|
class ProfNode:
|
||
|
|
def __init__(self, profiler, pc=0):
|
||
|
|
self.profiler = profiler
|
||
|
|
self.pc = pc
|
||
|
|
self.name = "NOT SET"
|
||
|
|
self.call_count = 0
|
||
|
|
self.children = {}
|
||
|
|
self.children_by_name = {}
|
||
|
|
|
||
|
|
def merge(self, node):
|
||
|
|
self.call_count += node.call_count
|
||
|
|
self.children = {**self.children, **node.children}
|
||
|
|
|
||
|
|
def add_stacktrace(self, stacktrace):
|
||
|
|
if len(stacktrace) == 0:
|
||
|
|
return
|
||
|
|
child_pc = stacktrace[-1]
|
||
|
|
if child_pc in self.children.keys():
|
||
|
|
self.children[child_pc].call_count += 1
|
||
|
|
else:
|
||
|
|
self.children[child_pc] = ProfNode(self.profiler, child_pc)
|
||
|
|
self.children[child_pc].call_count += 1
|
||
|
|
|
||
|
|
self.children[child_pc].add_stacktrace(stacktrace[:-1])
|
||
|
|
|
||
|
|
def process_node(self):
|
||
|
|
named_nodes = {}
|
||
|
|
|
||
|
|
for k, v in self.children.items():
|
||
|
|
v.process_node()
|
||
|
|
|
||
|
|
func_name = self.profiler.resolver().get(k)
|
||
|
|
if func_name in named_nodes.keys():
|
||
|
|
named_nodes[func_name].merge(v)
|
||
|
|
else:
|
||
|
|
named_nodes[func_name] = ProfNode(self.profiler)
|
||
|
|
named_nodes[func_name].name = func_name
|
||
|
|
named_nodes[func_name].merge(v)
|
||
|
|
self.children = named_nodes
|
||
|
|
|
||
|
|
def print(self, tabs=0):
|
||
|
|
print('{} {:>4} {}'.format(" "*tabs, self.call_count, self.name))
|
||
|
|
|
||
|
|
def trace(self, tabs=0):
|
||
|
|
self.print(tabs)
|
||
|
|
|
||
|
|
rd = sorted(self.children.values(),
|
||
|
|
key=lambda node: node.call_count, reverse=True)
|
||
|
|
for v in rd:
|
||
|
|
v.trace(tabs + 1)
|