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)