def test_garbage(self): with restore_gc_state(): gc.disable() a = [] b = [] c = [] a.append(a) b.append(c) c.append(b) del a, b, c graph = garbage() self.assertEqual(len(gc.garbage), 0) self.assertEqual(len(graph), 3) # A second call to garbage should # produce nothing new. graph2 = garbage() self.assertEqual(gc.garbage, []) self.assertEqual(len(graph2), 0) # But if we delete graph then # a, b and c become collectable again. del graph graph = garbage() self.assertEqual(gc.garbage, []) self.assertEqual(len(graph), 3) # Get rid of everything. del graph, graph2 gc.collect() graph = garbage() self.assertEqual(gc.garbage, []) self.assertEqual(len(graph), 0)
def tearDown(self): interesting = [] for o in gc.get_objects(): if isinstance(o, (torch.Tensor, Dim, Tensor, DimList)) and id(o) not in self.interesting: interesting.append(o) extra_memory = 0 if 'cuda' in self._testMethodName: extra_memory += torch.cuda.memory_allocated() - self.mem_allocated # nolevels = _n_levels_in_use() == 0 if extra_memory != 0 or len(interesting) != 0: import refcycle refcycle.garbage().export_image('garbage.pdf') gc.collect() # assert nolevels, f"cleanup failed? {_n_levels_in_use()}" assert extra_memory == 0, f'extra cuda memory left allocated: {extra_memory}' assert len(interesting) == 0, \ f'extra torch.Tensor, Dim, or Tensor left allocated: {len(interesting)} objects of types:' \ f' { [type(t) for t in interesting] }'
import refcycle import gc gc.disable() gc.collect() class A(object): pass a = A() b = A() a.foo = b b.foo = a del a, b, A graph = refcycle.garbage() graph.export_image('garbage.svg') graph.export_image('garbage.pdf') sccs = graph.strongly_connected_components() sccs sccs.sort(key=len) sccs[-1].export_image('scc1.svg') sccs[-1].export_image('scc1.pdf') sccs[-2].export_image('scc2.svg') sccs[-2].export_image('scc2.pdf') print(graph.source_components())