Return stats about memory use. Return a tuple with these items: - Dict from object kind to number of instances of that kind - Dict from object kind to total bytes used by all instances of that kind
()
| 18 | |
| 19 | |
| 20 | def collect_memory_stats() -> tuple[dict[str, int], dict[str, int]]: |
| 21 | """Return stats about memory use. |
| 22 | |
| 23 | Return a tuple with these items: |
| 24 | - Dict from object kind to number of instances of that kind |
| 25 | - Dict from object kind to total bytes used by all instances of that kind |
| 26 | """ |
| 27 | objs = gc.get_objects() |
| 28 | find_recursive_objects(objs) |
| 29 | |
| 30 | inferred = {} |
| 31 | for obj in objs: |
| 32 | if type(obj) is FakeInfo: |
| 33 | # Processing these would cause a crash. |
| 34 | continue |
| 35 | n = type(obj).__name__ |
| 36 | if hasattr(obj, "__dict__"): |
| 37 | # Keep track of which class a particular __dict__ is associated with. |
| 38 | inferred[id(obj.__dict__)] = f"{n} (__dict__)" |
| 39 | if isinstance(obj, (Node, Type)): # type: ignore[misc] |
| 40 | if hasattr(obj, "__dict__"): |
| 41 | for x in obj.__dict__.values(): |
| 42 | if isinstance(x, list): |
| 43 | # Keep track of which node a list is associated with. |
| 44 | inferred[id(x)] = f"{n} (list)" |
| 45 | if isinstance(x, tuple): |
| 46 | # Keep track of which node a list is associated with. |
| 47 | inferred[id(x)] = f"{n} (tuple)" |
| 48 | |
| 49 | for k in get_class_descriptors(type(obj)): |
| 50 | x = getattr(obj, k, None) |
| 51 | if isinstance(x, list): |
| 52 | inferred[id(x)] = f"{n} (list)" |
| 53 | if isinstance(x, tuple): |
| 54 | inferred[id(x)] = f"{n} (tuple)" |
| 55 | |
| 56 | freqs: dict[str, int] = {} |
| 57 | memuse: dict[str, int] = {} |
| 58 | for obj in objs: |
| 59 | if id(obj) in inferred: |
| 60 | name = inferred[id(obj)] |
| 61 | else: |
| 62 | name = type(obj).__name__ |
| 63 | freqs[name] = freqs.get(name, 0) + 1 |
| 64 | memuse[name] = memuse.get(name, 0) + sys.getsizeof(obj) |
| 65 | |
| 66 | return freqs, memuse |
| 67 | |
| 68 | |
| 69 | def print_memory_profile(run_gc: bool = True) -> None: |
no test coverage detected
searching dependent graphs…