1 files changed, 67 insertions, 0 deletions
diff --git a/tests/unittest.py b/tests/unittest.py
index c73195b32b..fa2ef51f49 100644
--- a/tests/unittest.py
+++ b/tests/unittest.py
@@ -227,13 +227,80 @@ class TestCase(unittest.TestCase):
@around(self)
def tearDown(orig: Callable[[], R]) -> R:
+ import sys
+ import time
+ import tracemalloc
+
ret = orig()
gc.collect(0)
# Run a full GC every 50 gen-0 GCs.
gen0_stats = gc.get_stats()[0]
gen0_collections = gen0_stats["collections"]
if gen0_collections % 50 == 0:
+ if not getattr(tracemalloc, "aaa", None):
+ tracemalloc.aaa = True
+ tracemalloc.start()
+ tracemalloc.s0 = tracemalloc.take_snapshot()
+ t0 = time.time()
gc.collect()
+ dt = time.time() - t0
+ s1 = tracemalloc.take_snapshot()
+ for line in s1.statistics("lineno")[:20]:
+ sys.stdout.write(f" {line}\n")
+ sys.stdout.write(f"full collection took {dt} s\n")
+ dt = time.time() - t0
+ sys.stdout.write(f"snapshot took {dt} s\n")
+ if dt > 1.5:
+
+ def dump_paths(o: object, max_distance: int) -> None:
+ import pdb
+ from collections import deque
+
+ queue: deque[object] = deque()
+ seen: set[int] = set()
+ prevs: Dict[int, object] = {}
+ roots: List[object] = []
+ distances: Dict[int, int] = {}
+ whitelist = {id(queue), id(seen), id(prevs), id(roots)}
+ i = 0
+ seen.add(id(o))
+ queue.append(o)
+ distances[id(o)] = 0
+ while len(queue) > 0:
+ o = queue.popleft()
+ has_referrers = False
+ if (
+ not isinstance(o, pdb.Pdb)
+ and distances[id(o)] < max_distance
+ ):
+ referrers = gc.get_referrers(o)
+ for referrer in referrers:
+ if id(referrer) in whitelist:
+ continue
+ has_referrers = True
+ if id(referrer) in seen:
+ continue
+ prevs[id(referrer)] = o
+ distances[id(referrer)] = distances[id(o)] + 1
+ seen.add(id(referrer))
+ queue.append(referrer)
+
+ if not has_referrers:
+ roots.append(o)
+
+ i += 1
+ print(f"{len(roots)} roots")
+ for root in roots:
+ o = root
+ while o is not None:
+ print(str(o)[:200])
+ o = prevs.get(id(o))
+ print("")
+ print(f"{len(roots)} roots")
+
+ import pdb
+
+ pdb.set_trace()
gc.enable()
set_current_context(SENTINEL_CONTEXT)
|