High-frequency sampler that tracks one pid's resource high-water marks.
| 187 | |
| 188 | |
| 189 | class ProcessMonitor: |
| 190 | """High-frequency sampler that tracks one pid's resource high-water marks.""" |
| 191 | |
| 192 | def __init__(self, pid: int): |
| 193 | self.pid = pid |
| 194 | self.first: ProcSample | None = None |
| 195 | self.last: ProcSample | None = None |
| 196 | self.peak_rss = 0 |
| 197 | self.peak_rss_anon = 0 |
| 198 | self.peak_pss = 0 |
| 199 | self.peak_swap = 0 |
| 200 | self.peak_threads = 0 |
| 201 | self.peak_fds = 0 |
| 202 | self.start = time.perf_counter() |
| 203 | self.end = self.start |
| 204 | self.n = 0 |
| 205 | |
| 206 | def poll(self) -> bool: |
| 207 | s = sample_proc(self.pid) |
| 208 | if s is None: |
| 209 | return False |
| 210 | self.n += 1 |
| 211 | self.end = time.perf_counter() |
| 212 | if self.first is None: |
| 213 | self.first = s |
| 214 | self.last = s |
| 215 | if s.rss_bytes: |
| 216 | self.peak_rss = max(self.peak_rss, s.rss_bytes) |
| 217 | if s.peak_rss_bytes: |
| 218 | self.peak_rss = max(self.peak_rss, s.peak_rss_bytes) |
| 219 | if s.rss_anon_bytes: |
| 220 | self.peak_rss_anon = max(self.peak_rss_anon, s.rss_anon_bytes) |
| 221 | if s.pss_bytes: |
| 222 | self.peak_pss = max(self.peak_pss, s.pss_bytes) |
| 223 | if s.swap_bytes: |
| 224 | self.peak_swap = max(self.peak_swap, s.swap_bytes) |
| 225 | if s.threads: |
| 226 | self.peak_threads = max(self.peak_threads, s.threads) |
| 227 | if s.fds: |
| 228 | self.peak_fds = max(self.peak_fds, s.fds) |
| 229 | return True |
| 230 | |
| 231 | def finalize(self) -> ResourceProfile: |
| 232 | p = ResourceProfile() |
| 233 | p.wall_ms = (self.end - self.start) * 1000.0 |
| 234 | p.samples = self.n |
| 235 | p.peak_rss_bytes = self.peak_rss |
| 236 | p.peak_rss_anon_bytes = self.peak_rss_anon |
| 237 | p.peak_pss_bytes = self.peak_pss |
| 238 | p.peak_swap_bytes = self.peak_swap |
| 239 | p.peak_threads = self.peak_threads |
| 240 | p.peak_fds = self.peak_fds |
| 241 | if self.last: |
| 242 | p.final_rss_bytes = self.last.rss_bytes or 0 |
| 243 | l = self.last |
| 244 | if l: |
| 245 | # Cumulative counters in /proc are totals since process birth. We |
| 246 | # monitor from spawn, so the final absolute value IS the total |
no outgoing calls
no test coverage detected