Skip to content

Types Module

Type definitions and data structures for profiling results.

Data Structures

ProfileBlock

stichotrope.types.ProfileBlock dataclass

Represents a single profiled code block with accumulated timing statistics.

Attributes:

Name Type Description
name str

Human-readable name of the block

file str

Source file where block is defined

line int

Line number where block is defined

hit_count int

Number of times this block was executed

total_time_ns int

Total accumulated time in nanoseconds

min_time_ns int

Minimum execution time in nanoseconds

max_time_ns int

Maximum execution time in nanoseconds

Source code in stichotrope/types.py
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
@dataclass
class ProfileBlock:
    """
    Represents a single profiled code block with accumulated timing statistics.

    Attributes:
        name: Human-readable name of the block
        file: Source file where block is defined
        line: Line number where block is defined
        hit_count: Number of times this block was executed
        total_time_ns: Total accumulated time in nanoseconds
        min_time_ns: Minimum execution time in nanoseconds
        max_time_ns: Maximum execution time in nanoseconds
    """

    name: str
    file: str
    line: int
    hit_count: int = 0
    total_time_ns: int = 0
    min_time_ns: int = 2**63 - 1  # Initialize to max int64
    max_time_ns: int = 0

    def record_time(self, elapsed_ns: int) -> None:
        """
        Record a single execution time for this block.

        Args:
            elapsed_ns: Elapsed time in nanoseconds
        """
        self.hit_count += 1
        self.total_time_ns += elapsed_ns
        self.min_time_ns = min(self.min_time_ns, elapsed_ns)
        self.max_time_ns = max(self.max_time_ns, elapsed_ns)

    @property
    def avg_time_ns(self) -> float:
        """Average execution time in nanoseconds."""
        return self.total_time_ns / self.hit_count if self.hit_count > 0 else 0.0

    def __repr__(self) -> str:
        return (
            f"ProfileBlock(name={self.name!r}, file={self.file!r}, line={self.line}, "
            f"hit_count={self.hit_count}, total_time_ns={self.total_time_ns}, "
            f"avg_time_ns={self.avg_time_ns:.0f}, min_time_ns={self.min_time_ns}, "
            f"max_time_ns={self.max_time_ns})"
        )

Attributes

avg_time_ns property

Average execution time in nanoseconds.

Functions

record_time(elapsed_ns)

Record a single execution time for this block.

Parameters:

Name Type Description Default
elapsed_ns int

Elapsed time in nanoseconds

required
Source code in stichotrope/types.py
34
35
36
37
38
39
40
41
42
43
44
def record_time(self, elapsed_ns: int) -> None:
    """
    Record a single execution time for this block.

    Args:
        elapsed_ns: Elapsed time in nanoseconds
    """
    self.hit_count += 1
    self.total_time_ns += elapsed_ns
    self.min_time_ns = min(self.min_time_ns, elapsed_ns)
    self.max_time_ns = max(self.max_time_ns, elapsed_ns)

ProfileTrack

stichotrope.types.ProfileTrack dataclass

Represents a logical track containing multiple profiled blocks.

Tracks provide logical grouping of profiling data (e.g., I/O, computation, database).

Attributes:

Name Type Description
track_idx int

Numeric index of this track

track_name Optional[str]

Optional human-readable name

enabled bool

Whether this track is currently enabled for profiling

blocks dict[int, ProfileBlock]

Dictionary mapping block_index -> ProfileBlock

Source code in stichotrope/types.py
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
@dataclass
class ProfileTrack:
    """
    Represents a logical track containing multiple profiled blocks.

    Tracks provide logical grouping of profiling data (e.g., I/O, computation, database).

    Attributes:
        track_idx: Numeric index of this track
        track_name: Optional human-readable name
        enabled: Whether this track is currently enabled for profiling
        blocks: Dictionary mapping block_index -> ProfileBlock
    """

    track_idx: int
    track_name: Optional[str] = None
    enabled: bool = True
    blocks: dict[int, ProfileBlock] = field(default_factory=dict)

    def add_block(self, block_idx: int, name: str, file: str, line: int) -> ProfileBlock:
        """
        Add a new block to this track.

        Args:
            block_idx: Unique index for this block within the track
            name: Human-readable name
            file: Source file
            line: Line number

        Returns:
            The created ProfileBlock
        """
        block = ProfileBlock(name=name, file=file, line=line)
        self.blocks[block_idx] = block
        return block

    def get_block(self, block_idx: int) -> Optional[ProfileBlock]:
        """Get a block by index, or None if not found."""
        return self.blocks.get(block_idx)

    @property
    def total_time_ns(self) -> int:
        """Total time across all blocks in this track."""
        return sum(block.total_time_ns for block in self.blocks.values())

    @property
    def total_hits(self) -> int:
        """Total hit count across all blocks in this track."""
        return sum(block.hit_count for block in self.blocks.values())

    def __repr__(self) -> str:
        name_str = f" ({self.track_name!r})" if self.track_name else ""
        return (
            f"ProfileTrack(track_idx={self.track_idx}{name_str}, "
            f"enabled={self.enabled}, blocks={len(self.blocks)}, "
            f"total_time_ns={self.total_time_ns}, total_hits={self.total_hits})"
        )

Attributes

total_hits property

Total hit count across all blocks in this track.

total_time_ns property

Total time across all blocks in this track.

Functions

add_block(block_idx, name, file, line)

Add a new block to this track.

Parameters:

Name Type Description Default
block_idx int

Unique index for this block within the track

required
name str

Human-readable name

required
file str

Source file

required
line int

Line number

required

Returns:

Type Description
ProfileBlock

The created ProfileBlock

Source code in stichotrope/types.py
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
def add_block(self, block_idx: int, name: str, file: str, line: int) -> ProfileBlock:
    """
    Add a new block to this track.

    Args:
        block_idx: Unique index for this block within the track
        name: Human-readable name
        file: Source file
        line: Line number

    Returns:
        The created ProfileBlock
    """
    block = ProfileBlock(name=name, file=file, line=line)
    self.blocks[block_idx] = block
    return block
get_block(block_idx)

Get a block by index, or None if not found.

Source code in stichotrope/types.py
96
97
98
def get_block(self, block_idx: int) -> Optional[ProfileBlock]:
    """Get a block by index, or None if not found."""
    return self.blocks.get(block_idx)

ProfilerResults

stichotrope.types.ProfilerResults dataclass

Complete profiling results for a profiler instance.

Attributes:

Name Type Description
profiler_name str

Name of the profiler instance

tracks dict[int, ProfileTrack]

Dictionary mapping track_idx -> ProfileTrack

Source code in stichotrope/types.py
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
@dataclass
class ProfilerResults:
    """
    Complete profiling results for a profiler instance.

    Attributes:
        profiler_name: Name of the profiler instance
        tracks: Dictionary mapping track_idx -> ProfileTrack
    """

    profiler_name: str
    tracks: dict[int, ProfileTrack] = field(default_factory=dict)

    @property
    def total_time_ns(self) -> int:
        """Total time across all tracks."""
        return sum(track.total_time_ns for track in self.tracks.values())

    @property
    def total_hits(self) -> int:
        """Total hit count across all tracks."""
        return sum(track.total_hits for track in self.tracks.values())

    def get_track(self, track_idx: int) -> Optional[ProfileTrack]:
        """Get a track by index, or None if not found."""
        return self.tracks.get(track_idx)

    def __repr__(self) -> str:
        return (
            f"ProfilerResults(profiler_name={self.profiler_name!r}, "
            f"tracks={len(self.tracks)}, total_time_ns={self.total_time_ns}, "
            f"total_hits={self.total_hits})"
        )

Attributes

total_hits property

Total hit count across all tracks.

total_time_ns property

Total time across all tracks.

Functions

get_track(track_idx)

Get a track by index, or None if not found.

Source code in stichotrope/types.py
142
143
144
def get_track(self, track_idx: int) -> Optional[ProfileTrack]:
    """Get a track by index, or None if not found."""
    return self.tracks.get(track_idx)

Usage Examples

Accessing Profile Data

from stichotrope import Profiler

profiler = Profiler("MyApp")

# ... run profiled code ...

# Get results
results = profiler.get_results()

# Access profiler name
print(f"Profiler: {results.profiler_name}")

# Iterate over tracks
for track in results.tracks:
    print(f"Track {track.track_idx}:")

    # Iterate over blocks in track
    for block in track.blocks:
        print(f"  Block {block.block_idx} ({block.name}):")
        print(f"    Duration: {block.duration_ns} ns")
        print(f"    Location: {block.file}:{block.line}")

Analyzing Results

from stichotrope import Profiler

profiler = Profiler("MyApp")

# ... run profiled code ...

results = profiler.get_results()

# Find slowest block
slowest_block = None
slowest_duration = 0

for track in results.tracks:
    for block in track.blocks:
        if block.duration_ns > slowest_duration:
            slowest_duration = block.duration_ns
            slowest_block = block

if slowest_block:
    print(f"Slowest block: {slowest_block.name}")
    print(f"Duration: {slowest_block.duration_ns} ns")
    print(f"Location: {slowest_block.file}:{slowest_block.line}")

Filtering Results

from stichotrope import Profiler

profiler = Profiler("MyApp")

# ... run profiled code ...

results = profiler.get_results()

# Filter blocks by duration threshold (e.g., > 1ms)
threshold_ns = 1_000_000  # 1ms in nanoseconds

slow_blocks = []
for track in results.tracks:
    for block in track.blocks:
        if block.duration_ns > threshold_ns:
            slow_blocks.append(block)

print(f"Found {len(slow_blocks)} blocks slower than 1ms")
for block in slow_blocks:
    print(f"  {block.name}: {block.duration_ns / 1_000_000:.2f} ms")

Aggregating Results

from stichotrope import Profiler
from collections import defaultdict

profiler = Profiler("MyApp")

# ... run profiled code ...

results = profiler.get_results()

# Aggregate by block name
aggregated = defaultdict(lambda: {"count": 0, "total_ns": 0})

for track in results.tracks:
    for block in track.blocks:
        aggregated[block.name]["count"] += 1
        aggregated[block.name]["total_ns"] += block.duration_ns

# Print aggregated results
for name, stats in aggregated.items():
    avg_ns = stats["total_ns"] / stats["count"]
    print(f"{name}:")
    print(f"  Count: {stats['count']}")
    print(f"  Total: {stats['total_ns'] / 1_000_000:.2f} ms")
    print(f"  Average: {avg_ns / 1_000_000:.2f} ms")

Track-Level Analysis

from stichotrope import Profiler

profiler = Profiler("MyApp")

# ... run profiled code ...

results = profiler.get_results()

# Analyze each track
for track in results.tracks:
    total_duration = sum(block.duration_ns for block in track.blocks)
    block_count = len(track.blocks)

    print(f"Track {track.track_idx}:")
    print(f"  Blocks: {block_count}")
    print(f"  Total duration: {total_duration / 1_000_000:.2f} ms")

    if block_count > 0:
        avg_duration = total_duration / block_count
        print(f"  Average duration: {avg_duration / 1_000_000:.2f} ms")

Type Hints

The types module provides type hints for better IDE support and type checking:

from stichotrope import Profiler, ProfilerResults
from stichotrope.types import ProfileBlock, ProfileTrack

def analyze_results(results: ProfilerResults) -> None:
    """Analyze profiling results with full type hints."""
    track: ProfileTrack
    for track in results.tracks:
        block: ProfileBlock
        for block in track.blocks:
            print(f"{block.name}: {block.duration_ns} ns")

profiler = Profiler("MyApp")
# ... run profiled code ...
analyze_results(profiler.get_results())

Data Structure Details

ProfileBlock Fields

  • block_idx (int): Unique index within the track
  • name (str): Human-readable block name
  • file (str): Source file path where block was defined
  • line (int): Line number where block was defined
  • duration_ns (int): Execution duration in nanoseconds

ProfileTrack Fields

  • track_idx (int): Track index
  • blocks (list[ProfileBlock]): List of profiling blocks in this track

ProfilerResults Fields

  • profiler_name (str): Name of the profiler instance
  • tracks (list[ProfileTrack]): List of tracks with profiling data

See Also