Collector that displays live top-like statistics using ncurses.
| 104 | |
| 105 | |
| 106 | class LiveStatsCollector(Collector): |
| 107 | """Collector that displays live top-like statistics using ncurses.""" |
| 108 | |
| 109 | def __init__( |
| 110 | self, |
| 111 | sample_interval_usec, |
| 112 | *, |
| 113 | skip_idle=False, |
| 114 | sort_by=DEFAULT_SORT_BY, |
| 115 | limit=DEFAULT_DISPLAY_LIMIT, |
| 116 | pid=None, |
| 117 | display=None, |
| 118 | mode=None, |
| 119 | opcodes=False, |
| 120 | async_aware=None, |
| 121 | ): |
| 122 | """ |
| 123 | Initialize the live stats collector. |
| 124 | |
| 125 | Args: |
| 126 | sample_interval_usec: Sampling interval in microseconds |
| 127 | skip_idle: Whether to skip idle threads |
| 128 | sort_by: Sort key ('tottime', 'nsamples', 'cumtime', 'sample_pct', 'cumul_pct') |
| 129 | limit: Maximum number of functions to display |
| 130 | pid: Process ID being profiled |
| 131 | display: DisplayInterface implementation (None means curses will be used) |
| 132 | mode: Profiling mode ('cpu', 'gil', etc.) - affects what stats are shown |
| 133 | opcodes: Whether to show opcode panel (requires --opcodes flag) |
| 134 | async_aware: Async tracing mode - None (sync only), "all" or "running" |
| 135 | """ |
| 136 | self.result = collections.defaultdict( |
| 137 | lambda: dict(total_rec_calls=0, direct_calls=0, cumulative_calls=0) |
| 138 | ) |
| 139 | self.sample_interval_usec = sample_interval_usec |
| 140 | self.sample_interval_sec = ( |
| 141 | sample_interval_usec / MICROSECONDS_PER_SECOND |
| 142 | ) |
| 143 | self.skip_idle = skip_idle |
| 144 | self.sort_by = sort_by |
| 145 | self.limit = limit |
| 146 | self.total_samples = 0 |
| 147 | self.start_time = None |
| 148 | self.stdscr = None |
| 149 | self.display = display # DisplayInterface implementation |
| 150 | self.running = True |
| 151 | self.pid = pid |
| 152 | self.mode = mode # Profiling mode |
| 153 | self.async_aware = async_aware # Async tracing mode |
| 154 | # Pre-select frame iterator method to avoid per-call dispatch overhead |
| 155 | self._get_frame_iterator = self._get_async_frame_iterator if async_aware else self._get_sync_frame_iterator |
| 156 | self._saved_stdout = None |
| 157 | self._saved_stderr = None |
| 158 | self._devnull = None |
| 159 | self._last_display_update = None |
| 160 | self.max_sample_rate = 0 # Track maximum sample rate seen |
| 161 | self.successful_samples = 0 # Track samples that captured frames |
| 162 | self.failed_samples = 0 # Track samples that failed to capture frames |
| 163 | self.display_update_interval_sec = DISPLAY_UPDATE_INTERVAL_SEC # Instance variable for display refresh rate |
no outgoing calls
searching dependent graphs…