Generate a dot graph from the output of several profilers.
—
Core classes representing profiler data structures including profiles, functions, calls, and cycles. These classes provide the foundation for all profiler data manipulation and analysis operations in gprof2dot.
The main container class that holds the entire profile data structure, including all functions, calls, and detected cycles.
class Profile:
def __init__(self):
"""Initialize a new empty profile."""
def add_function(self, function):
"""
Add a function to the profile.
Args:
function (Function): Function object to add
"""
def add_cycle(self, cycle):
"""
Add a cycle to the profile.
Args:
cycle (Cycle): Cycle object to add
"""
def validate(self):
"""Validate the profile data structure for consistency."""
def prune(self, node_thres, edge_thres, paths, color_nodes_by_selftime):
"""
Remove nodes and edges below specified thresholds.
Args:
node_thres (float): Minimum node weight threshold (0.0-1.0)
edge_thres (float): Minimum edge weight threshold (0.0-1.0)
paths: Path constraints
color_nodes_by_selftime (bool): Color nodes by self time
"""
def dump(self):
"""Print debug representation of the profile."""
def find_cycles(self):
"""
Find cycles using Tarjan's strongly connected components algorithm.
Identifies mutually recursive function groups and creates Cycle objects
containing them. Updates self.cycles with discovered cycles.
"""
def prune_root(self, roots, depth=-1):
"""
Prune call graph to show only descendants of specified root functions.
Args:
roots: Collection of root function IDs
depth (int): Maximum traversal depth (-1 for unlimited)
"""
def prune_leaf(self, leafs, depth=-1):
"""
Prune call graph to show only ancestors of specified leaf functions.
Args:
leafs: Collection of leaf function IDs
depth (int): Maximum traversal depth (-1 for unlimited)
"""
def getFunctionIds(self, funcName):
"""
Get function IDs matching a glob pattern.
Args:
funcName (str): Glob pattern for function names
Returns:
list: List of matching function IDs
"""
def getFunctionId(self, funcName):
"""
Get single function ID matching a name pattern.
Args:
funcName (str): Function name pattern
Returns:
Function ID or None if not found
"""Represents individual functions in the profile with their associated call relationships and performance metrics.
class Function:
def __init__(self, id, name):
"""
Initialize a new function.
Args:
id: Unique identifier
name (str): Function name
"""
def add_call(self, call):
"""
Add a call relationship to another function.
Args:
call (Call): Call object to add
"""
def get_call(self, callee_id):
"""
Get an existing call relationship.
Args:
callee_id: ID of the called function
Returns:
Call: The call object, or None if not found
"""
def dump(self):
"""Print debug representation of the function."""
def stripped_name(self):
"""
Remove extraneous information from C++ demangled function names.
Strips template parameters, function arguments, and const qualifiers
to create cleaner display names for visualization.
Returns:
str: Cleaned function name
"""Represents call relationships between functions, including performance metrics for each call edge.
class Call:
def __init__(self, callee_id):
"""
Initialize a new call relationship.
Args:
callee_id: ID of the called function
Note: Also initializes ratio and weight attributes to None.
"""
def dump(self):
"""Print debug representation of the call."""Represents groups of mutually recursive functions that form cycles in the call graph.
class Cycle:
def __init__(self):
"""
Initialize a new cycle.
Note: Cycles don't have IDs or names, they are containers for recursive function groups.
"""
def add_function(self, function):
"""
Add a function to this cycle.
Args:
function (Function): Function that is part of the cycle
"""Base class for all profile objects that can store event data (functions, calls, cycles).
class Object:
def __init__(self, events=None):
"""
Initialize object with optional events dictionary.
Args:
events (dict, optional): Event data dictionary
"""
def __hash__(self):
"""Return hash based on object identity."""
def __eq__(self, other):
"""Check equality based on object identity."""
def __lt__(self, other):
"""Less-than comparison based on object ID."""
def __getitem__(self, event):
"""
Get the value for a specific event type.
Args:
event (Event): Event type to retrieve
Returns:
Value for the event, or raises UndefinedEvent
"""
def __setitem__(self, event, value):
"""
Set the value for a specific event type.
Args:
event (Event): Event type to set
value: Value to set (None to delete)
"""
def __contains__(self, event):
"""
Check if this object has a value for the specified event.
Args:
event (Event): Event type to check
Returns:
bool: True if event is defined
"""Event types that define the metrics stored in profile objects.
class Event:
def __init__(self, name, null, aggregator, formatter=str):
"""
Initialize a new event type.
Args:
name (str): Event name
null: Null/default value for this event type
aggregator: Function to aggregate multiple values
formatter: Function to format values for display
"""
def __repr__(self):
"""Return string representation of the event."""
def null(self):
"""
Get the null/default value for this event type.
Returns:
The null value
"""
def aggregate(self, values):
"""
Aggregate multiple values using this event's aggregator.
Args:
values: Iterable of values to aggregate
Returns:
Aggregated result
"""
def format(self, value):
"""
Format a value for display using this event's formatter.
Args:
value: Value to format
Returns:
str: Formatted value
"""
class UndefinedEvent(Exception):
"""Exception raised when accessing undefined event values."""
def __init__(self, event):
"""
Initialize with the undefined event.
Args:
event (Event): The event that was undefined
"""import gprof2dot
# Create a new profile
profile = gprof2dot.Profile()
# Create functions
main_func = gprof2dot.Function(1, "main")
helper_func = gprof2dot.Function(2, "helper_function")
# Add functions to profile
profile.add_function(main_func)
profile.add_function(helper_func)
# Create call relationship
call = gprof2dot.Call(2) # main calls helper_function (id=2)
main_func.add_call(call)
# Set performance metrics
main_func[gprof2dot.TIME] = 100.0 # 100ms total time
call[gprof2dot.CALLS] = 5 # Called 5 times
# Validate and process
profile.validate()
profile.prune(0.01, 0.001, [], False) # Remove nodes <1%, edges <0.1%# Check if function has timing data
if gprof2dot.TIME in main_func:
time_value = main_func[gprof2dot.TIME]
formatted_time = gprof2dot.TIME.format(time_value)
print(f"Function time: {formatted_time}")
# Aggregate call counts
call_counts = [call[gprof2dot.CALLS] for call in main_func.calls.values()]
total_calls = gprof2dot.CALLS.aggregate(call_counts)Install with Tessl CLI
npx tessl i tessl/pypi-gprof2dot