| 364 | |
| 365 | |
| 366 | class Stats: |
| 367 | def __init__(self, data: RawData): |
| 368 | self._data = data |
| 369 | |
| 370 | def get(self, key: str) -> int: |
| 371 | return self._data.get(key, 0) |
| 372 | |
| 373 | @functools.cache |
| 374 | def get_opcode_stats(self, prefix: str) -> OpcodeStats: |
| 375 | opcode_stats = collections.defaultdict[str, dict](dict) |
| 376 | for key, value in self._data.items(): |
| 377 | if not key.startswith(prefix): |
| 378 | continue |
| 379 | name, _, rest = key[len(prefix) + 1 :].partition("]") |
| 380 | opcode_stats[name][rest.strip(".")] = value |
| 381 | return OpcodeStats( |
| 382 | opcode_stats, |
| 383 | self._data["_defines"], |
| 384 | self._data["_specialized_instructions"], |
| 385 | ) |
| 386 | |
| 387 | def get_call_stats(self) -> dict[str, int]: |
| 388 | defines = self._data["_stats_defines"] |
| 389 | result = {} |
| 390 | for key, value in sorted(self._data.items()): |
| 391 | if "Calls to" in key: |
| 392 | result[key] = value |
| 393 | elif key.startswith("Calls "): |
| 394 | name, index = key[:-1].split("[") |
| 395 | label = f"{name} ({pretty(defines[int(index)][0])})" |
| 396 | result[label] = value |
| 397 | |
| 398 | for key, value in sorted(self._data.items()): |
| 399 | if key.startswith("Frame"): |
| 400 | result[key] = value |
| 401 | |
| 402 | return result |
| 403 | |
| 404 | def get_object_stats(self) -> dict[str, tuple[int, int]]: |
| 405 | total_materializations = self._data.get("Object inline values", 0) |
| 406 | total_allocations = self._data.get("Object allocations", 0) + self._data.get( |
| 407 | "Object allocations from freelist", 0 |
| 408 | ) |
| 409 | total_increfs = ( |
| 410 | self._data.get("Object interpreter mortal increfs", 0) + |
| 411 | self._data.get("Object mortal increfs", 0) + |
| 412 | self._data.get("Object interpreter immortal increfs", 0) + |
| 413 | self._data.get("Object immortal increfs", 0) |
| 414 | ) |
| 415 | total_decrefs = ( |
| 416 | self._data.get("Object interpreter mortal decrefs", 0) + |
| 417 | self._data.get("Object mortal decrefs", 0) + |
| 418 | self._data.get("Object interpreter immortal decrefs", 0) + |
| 419 | self._data.get("Object immortal decrefs", 0) |
| 420 | ) |
| 421 | |
| 422 | result = {} |
| 423 | for key, value in self._data.items(): |
no outgoing calls
no test coverage detected
searching dependent graphs…