def test_datatype_copy1(self): A = make_dataclass("A", ('x', 'y'), varsize=True) a = A(1, 2, 3, 4, 5) self.assertEqual(gc.is_tracked(a), False) b = a.__copy__() self.assertEqual(gc.is_tracked(b), False) self.assertEqual(a, b)
def test_datatype_copy_dict(self): A = make_dataclass("A", ('x', 'y'), use_dict=True) a = A(1, 2, z=3, w=4) self.assertEqual(gc.is_tracked(a), False) b = a.__copy__() self.assertEqual(gc.is_tracked(b), False) self.assertEqual(a, b)
def _tracked(self, t): if sys.version_info[0] < 3: return else: # pragma: no cover self.assertTrue(gc.is_tracked(t), t) gc.collect() gc.collect() self.assertTrue(gc.is_tracked(t), t)
def test_copy_maintains_tracking(self): class A: pass key = A() for d in ({}, {'a': 1}, {key: 'val'}): d2 = d.copy() self.assertEqual(gc.is_tracked(d), gc.is_tracked(d2))
def test_not_tracked_by_gc(self): # PyPy doesn't have gc.is_tracked, but we don't # run these tests there. import gc from zodbpickle import binary s = b'abcdef' b = binary(s) self.assertFalse(gc.is_tracked(s)) self.assertFalse(gc.is_tracked(b))
def test_copy_maintains_tracking(self): class A: pass key = A() for d in (strdict({}), strdict({'a': 1}), strdict({repr(key): 'val'})): d2 = d.copy() self.assertEqual(gc.is_tracked(d), gc.is_tracked(d2))
def test_copy_maintains_tracking(self): class A: pass key = A() for d in (Dict(), Dict({"a": 1}), Dict({key: "val"})): d2 = d.copy() self.assertEqual(gc.is_tracked(d), gc.is_tracked(d2))
def test_untracked_containers(self): """Test whether untracked container objects are detected. """ untracked = {} tracked = {'untracked': untracked} self.assertTrue(gc.is_tracked(tracked)) self.assertFalse(gc.is_tracked(untracked)) objects = [id(o) for o in muppy.get_objects()] self.assertTrue(id(untracked) in objects)
def test_struct_gc_set_on_copy(): """Copying doesn't go through the struct constructor""" class Test(Struct): x: object y: object assert not gc.is_tracked(copy.copy(Test(1, 2))) assert not gc.is_tracked(copy.copy(Test(1, ()))) assert gc.is_tracked(copy.copy(Test(1, [])))
def test_struct_gc_set_on_unpickle(): """Unpickling doesn't go through the struct constructor""" class Test(quickle.Struct): x: object y: object ts = [Test(1, 2), Test(3, "hello"), Test([], ()), Test((), ())] a, b, c, d = quickle.loads(quickle.dumps(ts, registry=[Test]), registry=[Test]) assert not gc.is_tracked(a) assert not gc.is_tracked(b) assert gc.is_tracked(c) assert not gc.is_tracked(d)
def test_create0(self): gc.collect() cnt1 = gc.get_count() A = make_class("A", fields=2) B = make_class("B", varsize=True) b = B([], ()) a = A({}, b) cnt2 = gc.get_count() self.assertEqual(gc.is_tracked(a), False) self.assertEqual(gc.is_tracked(b), False) del a gc.collect() cnt3 = gc.get_count() self.assertEqual(cnt1, cnt3)
def test_gc_create0(self): gc.collect() cnt1 = gc.get_count() A = make_arrayclass("A", 2, gc=True) B = make_arrayclass("B", varsize=True, gc=True) b = B([], ()) a = A({}, b) cnt2 = gc.get_count() self.assertEqual(gc.is_tracked(a), True) self.assertEqual(gc.is_tracked(b), True) del a gc.collect() cnt3 = gc.get_count() self.assertEqual(cnt1, cnt3)
def test_gc_create0(self): gc.collect() cnt1 = gc.get_count() A = make_class("A", fields=2, gc=True) B = make_class("B", varsize=True, gc=True) b = B([], ()) a = A({}, b) cnt2 = gc.get_count() self.assertEqual(gc.is_tracked(a), True) self.assertEqual(gc.is_tracked(b), True) del a gc.collect() cnt3 = gc.get_count() self.assertEqual(cnt1, cnt3)
def test_subclass2(self): A = make_dataclass("A", ('x', 'y')) class B(A): __fields__ = ('z', ) class C(B): pass self.assertEqual(type(A), type(B)) self.assertEqual(type(C), type(B)) self.assertEqual(C.__dictoffset__, 0) self.assertEqual(C.__weakrefoffset__, 0) c = C(1, 2, 3) self.assertEqual(gc.is_tracked(c), False) self.assertEqual(repr(c), "C(x=1, y=2, z=3)") self.assertEqual(c.x, 1) self.assertEqual(c.y, 2) self.assertEqual(c.z, 3) self.assertEqual(asdict(c), {'x': 1, 'y': 2, 'z': 3}) self.assertEqual(sys.getsizeof(c), pyobject_size + 3 * ref_size) with self.assertRaises(TypeError): weakref.ref(c) with self.assertRaises(AttributeError): c.__dict__ c = None
def main(): a = 4 b = 5 c_list = [] c_list.append(123) c_list.append(456) # reference cycle c_list.append(c_list) c_list[2].append(789) # foo = ['hi'] # c_list = foo print(c_list) print("Stats: {}".format(gc.get_stats())) print("Count: {}".format(gc.get_count())) print("GC enabled: {}".format(gc.isenabled())) print("Threshold: {}".format(gc.get_threshold())) print("c_list is tracked: {}".format(gc.is_tracked(c_list))) """ The count returned is generally one higher than you might expect, because it includes the (temporary) reference as an argument to getrefcount(). """ print("Reference count for c_list: {}".format(sys.getrefcount(c_list))) del c_list[2] print("Reference count for c_list: {}".format(sys.getrefcount(c_list))) print("Collecting: {}".format(gc.collect())) print("Done.")
def erase(self, var): ''' Erase and remove variable from the shelf ''' if isinstance(var,str): name = var elif isinstance(var, ShelvedCommon): name = var.name if name == None: name = var.name_on_shelf # torch tensor special handling _decref(var) del var else: raise RuntimeError('bad erase parameter') print("ERASING >", name , "<") # check the thing we are trying to erase is on the shelf if not name in self.__dict__: raise RuntimeError('attempting to erase something that is not on the shelf') # sanity check if gc.is_tracked(self.__dict__[name]): gc.collect() # force gc count = sys.getrefcount(self.__dict__[name]) if count != 2: raise RuntimeError('erase failed due to outstanding references ({})'.format(count)) self.__dict__.pop(name) gc.collect() # force gc # then remove the named memory from the store self.mr.erase_named_memory(name)
def test_datatype_nosq_nomp(self): A = make_dataclass("A", ('x', 'y')) a = A(1, 2) self.assertEqual(gc.is_tracked(a), False) with self.assertRaises(TypeError): a[0] with self.assertRaises(TypeError): a['x']
def _not_tracked(self, t): if sys.version_info[0] < 3: return else: # pragma: no cover # Nested tuples can take several collections to untrack gc.collect() gc.collect() self.assertFalse(gc.is_tracked(t), t)
def _not_tracked(self, t): # Nested containers can take several collections to untrack gc.collect() gc.collect() # UserDict is tracked unlike normal dict so we have to change # this test for our Dict # self.assertFalse(gc.is_tracked(t), t) self.assertTrue(gc.is_tracked(t), t)
def test_datatype_nosq_mp(self): A = make_dataclass("A", ('x', 'y'), mapping=True) a = A(1, 2) self.assertEqual(gc.is_tracked(a), False) self.assertEqual(a['x'], 1) self.assertEqual(a['y'], 2) with self.assertRaises(TypeError): a[0]
def test_datatype_sq_nomp(self): A = make_dataclass("A", ('x', 'y'), sequence=True) a = A(1, 2) self.assertEqual(gc.is_tracked(a), False) self.assertEqual(a[0], 1) self.assertEqual(a[1], 2) with self.assertRaises(TypeError): a['x']
def test_gc_create1(self): gc.collect() cnt1 = gc.get_count() A = make_class("A", fields=2, gc=True) B = make_class("B", varsize=True, gc=True) C = make_class("C", fields=2, varsize=True, gc=True) b = A([], ()) c = C(1,2,{1:2,3:4},[1,2]) b1 = B(1, b) a = [b1, c] cnt2 = gc.get_count() self.assertEqual(gc.is_tracked(b), True) self.assertEqual(gc.is_tracked(b1), True) self.assertEqual(gc.is_tracked(c), True) del a gc.collect() cnt3 = gc.get_count() self.assertEqual(cnt1, cnt3)
def test_gc_create1(self): gc.collect() cnt1 = gc.get_count() A = make_arrayclass("A", 2, gc=True) B = make_arrayclass("B", varsize=True, gc=True) C = make_arrayclass("C", 2, varsize=True, gc=True) b = A([], ()) c = C(1,2,{1:2,3:4},[1,2]) b1 = B(1, b) a = [b1, c] cnt2 = gc.get_count() self.assertEqual(gc.is_tracked(b), True) self.assertEqual(gc.is_tracked(b1), True) self.assertEqual(gc.is_tracked(c), True) del a gc.collect() cnt3 = gc.get_count() self.assertEqual(cnt1, cnt3)
def test_datatype_sq_mp(self): A = make_dataclass("A", ('x', 'y'), sequence=True, mapping=True) a = A(1, 2) self.assertEqual(gc.is_tracked(a), False) self.assertEqual(a['x'], 1) self.assertEqual(a['y'], 2) self.assertEqual(a[0], 1) self.assertEqual(a[1], 2)
def test_enumerate_result_gc(self): # bpo-42536: enumerate's tuple-reuse speed trick breaks the GC's # assumptions about what can be untracked. Make sure we re-track result # tuples whenever we reuse them. it = self.enum([[]]) gc.collect() # That GC collection probably untracked the recycled internal result # tuple, which is initialized to (None, None). Make sure it's re-tracked # when it's mutated and returned from __next__: self.assertTrue(gc.is_tracked(next(it)))
def test_ordered_dict_items_result_gc(self): # bpo-42536: OrderedDict.items's tuple-reuse speed trick breaks the GC's # assumptions about what can be untracked. Make sure we re-track result # tuples whenever we reuse them. it = iter(self.OrderedDict({None: []}).items()) gc.collect() # That GC collection probably untracked the recycled internal result # tuple, which is initialized to (None, None). Make sure it's re-tracked # when it's mutated and returned from __next__: self.assertTrue(gc.is_tracked(next(it)))
def to_link(self, obj): try: title = object.__repr__(obj) except: title = '<unreprable %s object>' % obj.__class__.__name__ obj_bytes = self.to_bytes(obj) if gc.is_tracked(obj): return '<span title="%s">%s</span>' % (title, obj_bytes) return ('<a title="%s" href="%s">%s</a>' % (title, self.to_url(obj), obj_bytes))
def testGC(self): T = _Type([('a', 'I')]) self.assertTrue(gc.is_tracked(T)) R = weakref.ref(T) del T gc.collect() T = R() if T is not None: print("Not Dead!", T, gc.get_referrers(T)) self.assertIsNone(T)
def test_non_gc(self): with SimpleBase.test(): s = NonGC() self.assertFalse(gc.is_tracked(s)) ids = [id(s)] del s gc.collect() self.assert_del_calls(ids) self.assert_survivors([]) gc.collect() self.assert_del_calls(ids) self.assert_survivors([])
def test_non_gc_resurrect(self): with SimpleBase.test(): s = NonGCResurrector() self.assertFalse(gc.is_tracked(s)) ids = [id(s)] del s gc.collect() self.assert_del_calls(ids) self.assert_survivors(ids) self.clear_survivors() gc.collect() self.assert_del_calls(ids * 2) self.assert_survivors(ids)
def test_struct_gc_maybe_untracked_on_decode(self): class Test(msgspec.Struct): x: Any y: Any z: Tuple = () enc = msgspec.Encoder() dec = msgspec.Decoder(List[Test]) ts = [ Test(1, 2), Test(3, "hello"), Test([], []), Test({}, {}), Test(None, None, ()), ] a, b, c, d, e = dec.decode(enc.encode(ts)) assert not gc.is_tracked(a) assert not gc.is_tracked(b) assert gc.is_tracked(c) assert gc.is_tracked(d) assert not gc.is_tracked(e)
def get_all(type_obj, include_subtypes=True): """Get a list containing all instances of a given type. This will work for the vast majority of types out there. >>> class Ratking(object): pass >>> wiki, hak, sport = Ratking(), Ratking(), Ratking() >>> len(get_all(Ratking)) 3 However, there are some exceptions. For example, ``get_all(bool)`` returns an empty list because ``True`` and ``False`` are themselves built-in and not tracked. >>> get_all(bool) [] Still, it's not hard to see how this functionality can be used to find all instances of a leaking type and track them down further using :func:`gc.get_referrers` and :func:`gc.get_referents`. ``get_all()`` is optimized such that getting instances of user-created types is quite fast. Setting *include_subtypes* to ``False`` will further increase performance in cases where instances of subtypes aren't required. .. note:: There are no guarantees about the state of objects returned by ``get_all()``, especially in concurrent environments. For instance, it is possible for an object to be in the middle of executing its ``__init__()`` and be only partially constructed. """ # TODO: old-style classes if not isinstance(type_obj, type): raise TypeError('expected a type, not %r' % type_obj) try: type_is_tracked = gc.is_tracked(type_obj) except AttributeError: type_is_tracked = False # Python 2.6 and below don't get the speedup if type_is_tracked: to_check = gc.get_referrers(type_obj) else: to_check = gc.get_objects() if include_subtypes: ret = [x for x in to_check if isinstance(x, type_obj)] else: ret = [x for x in to_check if type(x) is type_obj] return ret
def run_test(): mytuple = tuple([1, 2, 3]) rfc = getrefptr(mytuple) self.assertTrue(gc.is_tracked(mytuple)) self.assertEqual(rfc.value, 1) b = mytuple self.assertEqual(rfc.value, 2) del b self.assertEqual(rfc.value, 1) _tuple_set_item(mytuple, 1, mytuple) self.assertEqual(rfc.value, 1) mytuple = None del mytuple return rfc
def recursive_sizeof(roots, skip_atomic=False): handler_cache = {} pending = collections.deque((root, root) for root in roots) visited = set() sizes = {id(root): 0 for root in roots} while pending: (obj, root) = pending.popleft() if id(obj) in visited: continue if not skip_atomic or gc.is_tracked(obj): sizes[id(root)] += sys.getsizeof(obj) visited.add(id(obj)) for child in enumerate_children(obj, handler_cache): if child is not None: pass pending.append((child, root)) results = [] for root in roots: results.append((root, sizes[id(root)])) return results
def _tracked(self, t): if sys.version_info[0] < 3: return self.assertTrue(gc.is_tracked(t), t) gc.collect() gc.collect() self.assertTrue(gc.is_tracked(t), t)
def test_is_tracked(self): if test_support.due_to_ironpython_incompatibility("http://ironpython.codeplex.com/workitem/17458"): return # Atomic built-in types are not tracked, user-defined objects and # mutable containers are. # NOTE: types with special optimizations (e.g. tuple) have tests # in their own test files instead. self.assertFalse(gc.is_tracked(None)) self.assertFalse(gc.is_tracked(1)) self.assertFalse(gc.is_tracked(1.0)) self.assertFalse(gc.is_tracked(1.0 + 5.0j)) self.assertFalse(gc.is_tracked(True)) self.assertFalse(gc.is_tracked(False)) self.assertFalse(gc.is_tracked("a")) self.assertFalse(gc.is_tracked(u"a")) self.assertFalse(gc.is_tracked(bytearray("a"))) self.assertFalse(gc.is_tracked(type)) self.assertFalse(gc.is_tracked(int)) self.assertFalse(gc.is_tracked(object)) self.assertFalse(gc.is_tracked(object())) class OldStyle: pass class NewStyle(object): pass self.assertTrue(gc.is_tracked(gc)) self.assertTrue(gc.is_tracked(OldStyle)) self.assertTrue(gc.is_tracked(OldStyle())) self.assertTrue(gc.is_tracked(NewStyle)) self.assertTrue(gc.is_tracked(NewStyle())) self.assertTrue(gc.is_tracked([])) self.assertTrue(gc.is_tracked(set()))
def test_is_tracked(self): # Atomic built-in types are not tracked, user-defined objects and # mutable containers are. # NOTE: types with special optimizations (e.g. tuple) have tests # in their own test files instead. self.assertFalse(gc.is_tracked(None)) self.assertFalse(gc.is_tracked(1)) self.assertFalse(gc.is_tracked(1.0)) self.assertFalse(gc.is_tracked(1.0 + 5.0j)) self.assertFalse(gc.is_tracked(True)) self.assertFalse(gc.is_tracked(False)) self.assertFalse(gc.is_tracked(b"a")) self.assertFalse(gc.is_tracked("a")) self.assertFalse(gc.is_tracked(bytearray(b"a"))) self.assertFalse(gc.is_tracked(type)) self.assertFalse(gc.is_tracked(int)) self.assertFalse(gc.is_tracked(object)) self.assertFalse(gc.is_tracked(object())) class UserClass: pass class UserInt(int): pass # Base class is object; no extra fields. class UserClassSlots: __slots__ = () # Base class is fixed size larger than object; no extra fields. class UserFloatSlots(float): __slots__ = () # Base class is variable size; no extra fields. class UserIntSlots(int): __slots__ = () self.assertTrue(gc.is_tracked(gc)) self.assertTrue(gc.is_tracked(UserClass)) self.assertTrue(gc.is_tracked(UserClass())) self.assertTrue(gc.is_tracked(UserInt())) self.assertTrue(gc.is_tracked([])) self.assertTrue(gc.is_tracked(set())) self.assertFalse(gc.is_tracked(UserClassSlots())) self.assertFalse(gc.is_tracked(UserFloatSlots())) self.assertFalse(gc.is_tracked(UserIntSlots()))
def _tracked(self, t): self.assertTrue(gc.is_tracked(t), t) gc.collect() gc.collect() self.assertTrue(gc.is_tracked(t), t)
def _not_tracked(self, t): # Nested containers can take several collections to untrack gc.collect() gc.collect() self.assertFalse(gc.is_tracked(t), t)
def garbagecollectortracking(self, widget): for i in self.Tischliste: a = i print gc.is_tracked(a)
def tolink(obj): if not gc.is_tracked(obj): return format('{0}', tolabel(obj)) return format('<a href="{0}">{1}</a>', id2url(id(obj)), tolabel(obj))
def check_slots(self, obj, base, extra): expected = sys.getsizeof(base) + struct.calcsize(extra) if gc.is_tracked(obj) and not gc.is_tracked(base): expected += self.gc_headsize self.assertEqual(sys.getsizeof(obj), expected)
def get_cell_html(self, value): inner = super(MetaTable, self).get_cell_html(value) if not gc.is_tracked(value): return inner return '<a href="/object/{0}">{1}</a>'.format(id(value), inner)
def test_is_tracked(self): # Atomic built-in types are not tracked, user-defined objects and # mutable containers are. # NOTE: types with special optimizations (e.g. tuple) have tests # in their own test files instead. self.assertFalse(gc.is_tracked(None)) self.assertFalse(gc.is_tracked(1)) self.assertFalse(gc.is_tracked(1.0)) self.assertFalse(gc.is_tracked(1.0 + 5.0j)) self.assertFalse(gc.is_tracked(True)) self.assertFalse(gc.is_tracked(False)) self.assertFalse(gc.is_tracked(b"a")) self.assertFalse(gc.is_tracked("a")) self.assertFalse(gc.is_tracked(bytearray(b"a"))) self.assertFalse(gc.is_tracked(type)) self.assertFalse(gc.is_tracked(int)) self.assertFalse(gc.is_tracked(object)) self.assertFalse(gc.is_tracked(object())) class UserClass: pass self.assertTrue(gc.is_tracked(gc)) self.assertTrue(gc.is_tracked(UserClass)) self.assertTrue(gc.is_tracked(UserClass())) self.assertTrue(gc.is_tracked([])) self.assertTrue(gc.is_tracked(set()))