MCPcopy Index your code
hub / github.com/python/cpython / FlamegraphCollector

Class FlamegraphCollector

Lib/profiling/sampling/stack_collector.py:66–445  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

64
65
66class FlamegraphCollector(StackTraceCollector):
67 def __init__(self, *args, **kwargs):
68 super().__init__(*args, **kwargs)
69 self.stats = {}
70 self._root = {"samples": 0, "children": {}, "threads": set()}
71 self._total_samples = 0
72 self._sample_count = 0 # Track actual number of samples (not thread traces)
73 self._func_intern = {}
74 self._string_table = StringTable()
75 self._all_threads = set()
76
77 # Thread status statistics (similar to LiveStatsCollector)
78 self.thread_status_counts = {
79 "has_gil": 0,
80 "on_cpu": 0,
81 "gil_requested": 0,
82 "unknown": 0,
83 "has_exception": 0,
84 "total": 0,
85 }
86 self.samples_with_gc_frames = 0
87
88 # Per-thread statistics
89 self.per_thread_stats = {} # {thread_id: {has_gil, on_cpu, gil_requested, unknown, has_exception, total, gc_samples}}
90
91 def collect(self, stack_frames, timestamps_us=None):
92 """Override to track thread status statistics before processing frames."""
93 # Weight is number of timestamps (samples with identical stack)
94 weight = len(timestamps_us) if timestamps_us else 1
95
96 # Increment sample count by weight
97 self._sample_count += weight
98
99 # Collect both aggregate and per-thread statistics using base method
100 status_counts, has_gc_frame, per_thread_stats = self._collect_thread_status_stats(stack_frames)
101
102 # Merge aggregate status counts (multiply by weight)
103 for key in status_counts:
104 self.thread_status_counts[key] += status_counts[key] * weight
105
106 # Update aggregate GC frame count
107 if has_gc_frame:
108 self.samples_with_gc_frames += weight
109
110 # Merge per-thread statistics (multiply by weight)
111 for thread_id, stats in per_thread_stats.items():
112 if thread_id not in self.per_thread_stats:
113 self.per_thread_stats[thread_id] = {
114 "has_gil": 0,
115 "on_cpu": 0,
116 "gil_requested": 0,
117 "unknown": 0,
118 "has_exception": 0,
119 "total": 0,
120 "gc_samples": 0,
121 }
122 for key, value in stats.items():
123 self.per_thread_stats[thread_id][key] += value * weight

Calls

no outgoing calls

Used in the wild real call sites across dependent graphs

searching dependent graphs…