Generate a dot graph from the output of several profilers.
—
DOT language generation with customizable themes, color schemes, and graph styling for creating publication-quality profiler visualizations. The visualization system converts parsed profile data into GraphViz DOT format with intelligent color-coding to highlight performance hotspots.
Main class responsible for converting profile data into GraphViz DOT language format with customizable styling and theming.
class DotWriter:
def __init__(self, fp):
"""
Initialize DOT writer.
Args:
fp: File-like object to write DOT output
"""
def graph(self, profile, theme):
"""
Generate complete DOT graph from profile data.
Args:
profile (Profile): Parsed profile data
theme (Theme): Color theme for visualization
"""
def node(self, node, **attrs):
"""
Generate DOT node definition.
Args:
node: Node identifier
**attrs: DOT attributes for the node
"""
def edge(self, src, dst, **attrs):
"""
Generate DOT edge definition.
Args:
src: Source node identifier
dst: Destination node identifier
**attrs: DOT attributes for the edge
"""
def begin_graph(self):
"""Begin DOT graph definition."""
def end_graph(self):
"""End DOT graph definition."""Customizable color themes that map performance metrics to visual properties like colors, line weights, and node sizes.
class Theme:
def __init__(self, bgcolor=(0.0, 0.0, 1.0), mincolor=(0.0, 0.0, 0.0), maxcolor=(0.0, 0.0, 1.0),
fontname="Arial", fontcolor="white", nodestyle="filled",
minfontsize=10.0, maxfontsize=10.0, minpenwidth=0.5, maxpenwidth=4.0,
gamma=2.2, skew=1.0):
"""
Initialize visualization theme.
Args:
bgcolor (tuple): Background color HSL values (0.0-1.0)
mincolor (tuple): Color for minimum values HSL (0.0-1.0)
maxcolor (tuple): Color for maximum values HSL (0.0-1.0)
fontname (str): Font family name
fontcolor (str): Font color
nodestyle (str): Node styling options
minfontsize (float): Minimum font size in points
maxfontsize (float): Maximum font size in points
minpenwidth (float): Minimum pen width for edges
maxpenwidth (float): Maximum pen width for edges
gamma (float): Gamma correction for color mapping
skew (float): Skew factor for color distribution
"""
def graph_bgcolor(self):
"""
Get background color for the graph.
Returns:
str: DOT color specification
"""
def node_bgcolor(self, weight):
"""
Get background color for a node based on its weight.
Args:
weight (float): Node weight/importance (0.0-1.0)
Returns:
str: DOT color specification
"""
def node_fgcolor(self, weight):
"""
Get foreground color for a node.
Args:
weight (float): Node weight/importance (0.0-1.0)
Returns:
str: DOT color specification
"""
def node_fontsize(self, weight):
"""
Get font size for node text based on weight.
Args:
weight (float): Node weight/importance (0.0-1.0)
Returns:
float: Font size in points
"""
def node_style(self):
"""
Get node styling attributes.
Returns:
str: DOT style specification
"""
def edge_color(self, weight):
"""
Get color for an edge based on its weight.
Args:
weight (float): Edge weight/importance (0.0-1.0)
Returns:
str: DOT color specification
"""
def edge_fontsize(self, weight):
"""
Get font size for edge labels based on weight.
Args:
weight (float): Edge weight/importance (0.0-1.0)
Returns:
float: Font size in points
"""
def edge_penwidth(self, weight):
"""
Get pen width for edges based on weight.
Args:
weight (float): Edge weight/importance (0.0-1.0)
Returns:
float: Pen width
"""
def edge_arrowsize(self, weight):
"""
Get arrow size for edges based on weight.
Args:
weight (float): Edge weight/importance (0.0-1.0)
Returns:
float: Arrow size
"""Ready-to-use color themes optimized for different visualization needs and output formats.
TEMPERATURE_COLORMAP: Theme
"""Blue to red temperature-style color scheme (default)."""
PINK_COLORMAP: Theme
"""Pink to red color scheme for alternative styling."""
GRAY_COLORMAP: Theme
"""Grayscale color scheme for monochrome output."""
BW_COLORMAP: Theme
"""Black and white color scheme for high contrast."""
PRINT_COLORMAP: Theme
"""Print-friendly color scheme optimized for paper output."""Dictionary mapping theme names to Theme objects for easy selection.
themes = {
'color': TEMPERATURE_COLORMAP,
'pink': PINK_COLORMAP,
'gray': GRAY_COLORMAP,
'bw': BW_COLORMAP,
'print': PRINT_COLORMAP
}Helper functions for consistent formatting and color processing.
def sorted_iteritems(d):
"""
Iterate dictionary items in sorted order for reproducible output.
Args:
d (dict): Dictionary to iterate
Yields:
tuple: (key, value) pairs in sorted order
"""
def times(x):
"""
Format multiplication count with Unicode symbol.
Args:
x (int): Count value
Returns:
str: Formatted count (e.g., "5×")
"""
def percentage(p):
"""
Format percentage value.
Args:
p (float): Percentage as decimal (0.0-1.0)
Returns:
str: Formatted percentage (e.g., "25.50%")
"""import gprof2dot
import sys
# Parse profile data
parser = gprof2dot.PstatsParser()
with open('profile.stats', 'rb') as f:
profile = parser.parse(f)
# Generate DOT output with default theme
theme = gprof2dot.TEMPERATURE_COLORMAP
dot_writer = gprof2dot.DotWriter(sys.stdout)
dot_writer.graph(profile, theme)import gprof2dot
# Use different predefined themes
themes_to_try = ['color', 'pink', 'gray', 'bw', 'print']
for theme_name in themes_to_try:
theme = gprof2dot.themes[theme_name]
with open(f'profile_{theme_name}.dot', 'w') as f:
dot_writer = gprof2dot.DotWriter(f)
dot_writer.graph(profile, theme)import gprof2dot
# Create custom theme with specific colors
custom_theme = gprof2dot.Theme(
bgcolor=(1.0, 1.0, 1.0), # White background
mincolor=(0.0, 1.0, 0.0), # Green for low values
maxcolor=(1.0, 0.0, 0.0), # Red for high values
fontname="Helvetica",
fontsize="12",
fontcolor="black",
nodestyle="filled,rounded",
edgestyle="bold"
)
# Use custom theme
dot_writer = gprof2dot.DotWriter(sys.stdout)
dot_writer.graph(profile, custom_theme)import gprof2dot
import subprocess
import sys
# Generate DOT and convert to various formats
def generate_visualization(profile, theme, output_file, format='png'):
"""Generate visualization in specified format."""
# Generate DOT
dot_process = subprocess.Popen(
['dot', f'-T{format}', '-o', output_file],
stdin=subprocess.PIPE,
text=True
)
dot_writer = gprof2dot.DotWriter(dot_process.stdin)
dot_writer.graph(profile, theme)
dot_process.stdin.close()
dot_process.wait()
# Usage
theme = gprof2dot.TEMPERATURE_COLORMAP
generate_visualization(profile, theme, 'profile.png', 'png')
generate_visualization(profile, theme, 'profile.svg', 'svg')
generate_visualization(profile, theme, 'profile.pdf', 'pdf')import gprof2dot
class CustomDotWriter(gprof2dot.DotWriter):
"""Custom DOT writer with additional formatting."""
def begin_graph(self):
super().begin_graph()
# Add custom graph attributes
self.fp.write(' rankdir=TB;\n') # Top-to-bottom layout
self.fp.write(' concentrate=true;\n') # Merge similar edges
def node(self, node, theme):
# Add custom node processing
if hasattr(node, 'is_main') and node.is_main:
# Highlight main function differently
self.fp.write(f' "{node.id}" [shape=doublecircle];\n')
else:
super().node(node, theme)
# Use custom writer
custom_writer = CustomDotWriter(sys.stdout)
custom_writer.graph(profile, theme)import gprof2dot
def analyze_color_mapping(profile, theme):
"""Analyze how colors map to performance metrics."""
for function in profile.functions.values():
if gprof2dot.TOTAL_TIME_RATIO in function:
weight = function[gprof2dot.TOTAL_TIME_RATIO]
bgcolor = theme.node_bgcolor(weight)
fgcolor = theme.node_fgcolor(weight)
print(f"Function {function.name}:")
print(f" Weight: {weight:.3f}")
print(f" Background: {bgcolor}")
print(f" Foreground: {fgcolor}")Install with Tessl CLI
npx tessl i tessl/pypi-gprof2dot