def __init__(self, excluded_obj: Optional[Union[object, str]] = None) -> None: self.sizer = asizeof.Asizer() self.excluded = [] if excluded_obj is not None: self.set_excluded_asizer(excluded_obj)
def create_snapshot(self, description='', compute_total=False): """ Collect current per instance statistics and saves total amount of memory associated with the Python process. If `compute_total` is `True`, the total consumption of all objects known to *asizeof* is computed. The latter might be very slow if many objects are mapped into memory at the time the snapshot is taken. Therefore, `compute_total` is set to `False` by default. The overhead of the `ClassTracker` structure is also computed. Snapshots can be taken asynchronously. The function is protected with a lock to prevent race conditions. """ try: # TODO: It is not clear what happens when memory is allocated or # released while this function is executed but it will likely lead # to inconsistencies. Either pause all other threads or don't size # individual objects in asynchronous mode. self.snapshot_lock.acquire() timestamp = _get_time() sizer = asizeof.Asizer() objs = [tobj.ref() for tobj in list(self.objects.values())] sizer.exclude_refs(*objs) # The objects need to be sized in a deterministic order. Sort the # objects by its creation date which should at least work for # non-parallel execution. The "proper" fix would be to handle # shared data separately. tracked_objects = list(self.objects.values()) tracked_objects.sort(key=lambda x: x.birth) for tobj in tracked_objects: tobj.track_size(timestamp, sizer) snapshot = Snapshot() snapshot.timestamp = timestamp snapshot.tracked_total = sizer.total if compute_total: snapshot.asizeof_total = asizeof.asizeof(all=True, code=True) snapshot.system_total = pympler.process.ProcessMemoryInfo() snapshot.desc = str(description) # Compute overhead of all structures, use sizer to exclude tracked # objects(!) snapshot.overhead = 0 if snapshot.tracked_total: snapshot.overhead = sizer.asizeof(self) if snapshot.asizeof_total: snapshot.asizeof_total -= snapshot.overhead self.snapshots.append(snapshot) finally: self.snapshot_lock.release()
def track_object(obj, msg=None): """Track sizeof obj. Only when testing w/ pympler installed""" if not _testing or not asizeof: return sizer = asizeof.Asizer() sizer.exclude_types(_excludes) tracked_objects[id(obj)].append( (time.time(), obj, sizer.asizeof(obj) / 1024.0, msg) )
def test_asizer(self): '''Test Asizer properties. ''' sizer = asizeof.Asizer() obj = 'unladen swallow' mutable = [obj] sizer.asizeof(obj) self.assertEqual(sizer.total, asizeof.asizeof(obj)) sizer.asizeof(mutable, mutable) self.assertEqual(sizer.duplicate, 1) self.assertEqual(sizer.total, asizeof.asizeof(obj, mutable))
def test_asizer_limit(self): '''Test limit setting for Asizer. ''' objs = [Foo(42), ThinFoo("spam"), OldFoo(67)] sizer = [asizeof.Asizer() for _ in range(4)] for limit, asizer in enumerate(sizer): asizer.asizeof(objs, limit=limit) limit_sizes = [asizer.total for asizer in sizer] self.assertTrue(limit_sizes[0] < limit_sizes[1], limit_sizes) self.assertTrue(limit_sizes[1] < limit_sizes[2], limit_sizes) self.assertTrue(limit_sizes[2] < limit_sizes[3], limit_sizes)
def track_object(obj, msg=None): if not asizeof: return # Only track if testing sizer = asizeof.Asizer() sizer.exclude_types(_excludes) if not _testing: return tracked_objects[id(obj)].append( (time.time(), obj, sizer.asizeof(obj) / 1024.0, msg))
def test_asized(self): '''Test asizeof.asized() ''' self.assertEqual(list(asizeof.asized(detail=2)), []) self.assertRaises(KeyError, asizeof.asized, **{'all': True}) sized = asizeof.asized(Foo(42), detail=2) self.assert_("Foo" in sized.name, sized.name) refs = [ref for ref in sized.refs if ref.name == '__dict__'] self.assertEqual(len(refs), 1) refs = [ref for ref in refs[0].refs if ref.name == '[V] data: 42'] self.assertEqual(len(refs), 1, refs) i = 42 self.assertEqual(refs[0].size, asizeof.asizeof(i), refs[0].size) # Size multiple objects sizer = asizeof.Asizer() sized_objs = sizer.asized(Foo(3), Foo(4), detail=2) self.assertEqual(len(sized_objs), 2)
def test_asizesof(self): '''Test asizeof.asizesof() ''' self.assertEqual(list(asizeof.asizesof()), []) self.assertRaises(KeyError, asizeof.asizesof, **{'all': True}) objs = [Foo(42), ThinFoo("spam"), OldFoo(67)] sizes = list(asizeof.asizesof(*objs)) objs.reverse() rsizes = list(asizeof.asizesof(*objs)) self.assertEqual(len(sizes), 3) rsizes.reverse() self.assertEqual(sizes, rsizes, (sizes, rsizes)) objs.reverse() isizes = [asizeof.asizeof(obj) for obj in objs] self.assertEqual(sizes, isizes) sizer = asizeof.Asizer() asizer_sizes = sizer.asizesof(*objs) self.assertEqual(list(asizer_sizes), sizes) code_sizes = sizer.asizesof(*objs, **dict(code=True)) self.failIfEqual(list(code_sizes), sizes)
def test_exclude_types(self): '''Test Asizer.exclude_types(). ''' sizer = asizeof.Asizer() sizer.exclude_types(Foo) self.assertEqual(sizer.asizeof(Foo('ignored')), 0)