Encapsulates all profiling data for a single thread.
| 51 | |
| 52 | @dataclass |
| 53 | class ThreadData: |
| 54 | """Encapsulates all profiling data for a single thread.""" |
| 55 | |
| 56 | thread_id: int |
| 57 | |
| 58 | # Function call statistics: {location: {direct_calls: int, cumulative_calls: int}} |
| 59 | result: dict = field(default_factory=lambda: collections.defaultdict( |
| 60 | lambda: dict(direct_calls=0, cumulative_calls=0) |
| 61 | )) |
| 62 | |
| 63 | # Thread status statistics |
| 64 | has_gil: int = 0 |
| 65 | on_cpu: int = 0 |
| 66 | gil_requested: int = 0 |
| 67 | unknown: int = 0 |
| 68 | has_exception: int = 0 |
| 69 | total: int = 0 # Total status samples for this thread |
| 70 | |
| 71 | # Sample counts |
| 72 | sample_count: int = 0 |
| 73 | gc_frame_samples: int = 0 |
| 74 | |
| 75 | # Opcode statistics: {location: {opcode: count}} |
| 76 | opcode_stats: dict = field(default_factory=lambda: collections.defaultdict( |
| 77 | lambda: collections.defaultdict(int) |
| 78 | )) |
| 79 | |
| 80 | def increment_status_flag(self, status_flags): |
| 81 | """Update status counts based on status bit flags.""" |
| 82 | if status_flags & THREAD_STATUS_HAS_GIL: |
| 83 | self.has_gil += 1 |
| 84 | if status_flags & THREAD_STATUS_ON_CPU: |
| 85 | self.on_cpu += 1 |
| 86 | if status_flags & THREAD_STATUS_GIL_REQUESTED: |
| 87 | self.gil_requested += 1 |
| 88 | if status_flags & THREAD_STATUS_UNKNOWN: |
| 89 | self.unknown += 1 |
| 90 | if status_flags & THREAD_STATUS_HAS_EXCEPTION: |
| 91 | self.has_exception += 1 |
| 92 | self.total += 1 |
| 93 | |
| 94 | def as_status_dict(self): |
| 95 | """Return status counts as a dict for compatibility.""" |
| 96 | return { |
| 97 | "has_gil": self.has_gil, |
| 98 | "on_cpu": self.on_cpu, |
| 99 | "gil_requested": self.gil_requested, |
| 100 | "unknown": self.unknown, |
| 101 | "has_exception": self.has_exception, |
| 102 | "total": self.total, |
| 103 | } |
| 104 | |
| 105 | |
| 106 | class LiveStatsCollector(Collector): |
no test coverage detected
searching dependent graphs…