Source code for hatchet.readers.gprof_dot_reader

# Copyright 2017-2023 Lawrence Livermore National Security, LLC and other
# Hatchet Project Developers. See the top-level LICENSE file for details.
#
# SPDX-License-Identifier: MIT

import re

import pandas as pd
import pydot

import hatchet.graphframe
from ..node import Node
from ..graph import Graph
from ..frame import Frame
from ..util.timer import Timer
from ..util.config import dot_keywords


[docs]class GprofDotReader: """Read in gprof/callgrind output in dot format generated by gprof2dot.""" def __init__(self, filename): self.dotfile = filename self.name_to_hnode = {} self.name_to_dict = {} self.timer = Timer()
[docs] def create_graph(self): """Read the DOT files to create a graph.""" graphs = pydot.graph_from_dot_file(self.dotfile, encoding="utf-8") for graph in graphs: for edge in graph.get_edges(): src_name = edge.get_source().strip('"') dst_name = edge.get_destination().strip('"') src_hnode = self.name_to_hnode.get(src_name) if not src_hnode: # create a node if it doesn't exist yet src_hnode = Node( Frame({"type": "function", "name": src_name}), None ) self.name_to_hnode[src_name] = src_hnode dst_hnode = self.name_to_hnode.get(dst_name) if not dst_hnode: # create a node if it doesn't exist yet dst_hnode = Node( Frame({"type": "function", "name": dst_name}), src_hnode ) self.name_to_hnode[dst_name] = dst_hnode # add source node as parent dst_hnode.add_parent(src_hnode) # add destination node as child src_hnode.add_child(dst_hnode) for node in graph.get_nodes(): node_name = node.get_name() if node_name not in dot_keywords: node_name = node_name.strip('"') hnode = self.name_to_hnode.get(node_name) if not hnode: # create a node if it doesn't exist yet hnode = Node( Frame({"type": "function", "name": node_name}), None ) self.name_to_hnode[node_name] = hnode if node.obj_dict["attributes"].get("label") is None: continue node_label = node.obj_dict["attributes"].get("label").strip('"') module, _, inc, exc, _ = node_label.split(r"\n") inc_time = float(re.sub(r"\%", "", inc)) exc_time = float(re.sub(r"[\(\%\)]", "", exc)) # create a dict with node properties node_dict = { "module": module, "name": node_name, "time (inc)": inc_time, "time": exc_time, "node": hnode, } self.name_to_dict[node_name] = node_dict # add all nodes with no parents to the list of roots list_roots = [] for (key, val) in self.name_to_hnode.items(): if not val.parents: list_roots.append(val) return list_roots
[docs] def read(self): """Read the DOT file generated by gprof2dot to create a graphframe. The DOT file contains a call graph. """ with self.timer.phase("graph construction"): roots = self.create_graph() graph = Graph(roots) graph.enumerate_traverse() with self.timer.phase("data frame"): dataframe = pd.DataFrame.from_dict(data=list(self.name_to_dict.values())) index = ["node"] dataframe.set_index(index, inplace=True) dataframe.sort_index(inplace=True) return hatchet.graphframe.GraphFrame(graph, dataframe, ["time"], ["time (inc)"])