def sovle_circle_quote_with_weak_ref(): # 1. 定义了两个类 class Person: def __del__(self): print("Person对象, 被释放了") pass class Dog: def __del__(self): print("Dog对象, 被释放了") pass p = Person() d = Dog() p.pet = d d.master = weakref.ref(p) del p del d gc.collect() print(objgraph.count("Person")) print(objgraph.count("Dog"))
def solve_cirecle_quote(): # 1. 定义了两个类 class Person: def __del__(self): print("Person对象, 被释放了") pass class Dog: def __del__(self): print("Dog对象, 被释放了") pass p = Person() d = Dog() p.pet = d d.master = p p.pet = None # 强制置 None del p del d gc.collect() print(objgraph.count("Person")) print(objgraph.count("Dog"))
def test_memory_cleanup_with_till(self): objgraph.growth() root = Signal() for i in range(100000): if i % 1000 == 0: Log.note("at {{num}} tills", num=i) root = root | Till(seconds=100000) mid_mem = psutil.Process(os.getpid()).memory_info().rss if mid_mem > 1000 * 1000 * 1000: Log.note("{{num}} Till triggers created", num=i) break trigger = Signal() root = root | trigger growth = objgraph.growth(limit=4) growth and Log.note("More object\n{{growth}}", growth=growth) trigger.go() root.wait() # THERE SHOULD BE NO DELAY HERE for _ in range(0, 20): try: Till(seconds=0.1).wait() # LET TIMER DAEMON CLEANUP current = [(t, objgraph.count(t), objgraph.count(t) - c) for t, c, d in growth] Log.note("Object count\n{{current}}", current=current) # NUMBER OF OBJECTS CLEANED UP SHOULD MATCH NUMBER OF OBJECTS CREATED for (_, _, cd), (_, _, gd) in zip(current, growth): self.assertAlmostEqual(-cd, gd, places=2) return except Exception as e: pass Log.error("object counts did not go down")
def test_no_new_reference_cycles(self): # Similar to https://github.com/mgedmin/objgraph/pull/22 but for # count() gc.disable() x = type('MyClass', (), {})() self.assertEqual(len(gc.get_referrers(x)), 1) objgraph.count('MyClass') self.assertEqual(len(gc.get_referrers(x)), 1)
def main1(): processes = [Process(target=main0) for _ in range(4)] for process in processes: process.start() for idx in range(100): print(objgraph.count('OBJ')) time.sleep(.5)
def test_leak(self, container_factory, service_cls, config): # regression test for # https://github.com/mattbennett/nameko-sentry/issues/12 container = container_factory(service_cls, config) container.start() gc.collect() count_before = objgraph.count('raven.breadcrumbs.BreadcrumbBuffer') with entrypoint_hook(container, 'broken') as hook: for _ in range(5): with pytest.raises(CustomException): hook() gc.collect() count_after = objgraph.count('raven.breadcrumbs.BreadcrumbBuffer') assert count_before == count_after
def main0(): for idx in range(40): time.sleep(1) func_to_leak() if idx == 20: print( gc.collect() ) # 手动执行垃圾回收,返回不可达(unreachable objects)对象的数目,循环引用需要垃圾回收,无法通过引用计数法消除 print(os.getpid(), objgraph.count('OBJ'), gc.get_count())
def object_count(self, object_type: str) -> int: """Gets number of object with type object_type in memory Arguments: object_type {str} -- object type Returns: int -- [description] """ return count(object_type)
def objgraph_count_types(self, args): """ This function can be used to display the number of objects for one or several types of objects. For now this works best for fuglu with thread backend. Fuglu has to be running as a daemon. "fuglu_control" is used to communicate with the fuglu instance. Examples: (1) Count ans sum objects given by a list ----------------------------------------- $ fuglu_control objgraph_count_types '{"typelist":["Worker","Suspect","SessionHandler"]}' --------------- Count suspects: --------------- params: * typelist: Worker,Suspect,SessionHandler Object types found in memory: Worker : 2 Suspect : 0 SessionHandler : 1 """ res = u"---------------\n" \ + u"Count suspects:\n" \ + u"---------------\n\n" defaults = { "typelist": ["Suspect", "Mailattachment", "Mailattachment_mgr"] } if OBJGRAPH_EXTENSION_ENABLED: if not args: args = {} # fill filter lists and other vars from dict res, inputdict = ControlSession.prepare_objectgraph_list_from_dict( args, res, defaults) try: res += u"Object types found in memory:\n" for otype in inputdict["typelist"]: n_otypes = objgraph.count(otype) res += u"%s : %u\n" % (otype, n_otypes) except Exception as e: res += u"ERROR: %s" % force_uString(e) self.logger.exception(e) else: res += u"please install module 'objgraph'" return res
def run_objgraph(types): import objgraph import os import random objgraph.show_most_common_types(limit=50, shortnames=False) for type_ in types: count = objgraph.count(type_) print '%s objects: %d' % (type_, count) if count: objgraph.show_backrefs( random.choice(objgraph.by_type(type_)), max_depth=20, filename='/tmp/backrefs_%s_%d.dot' % (type_, os.getpid()))
def main(): x = WithDel() y = [] z = [] x.append(y) y.append(z) z.append(x) del x, y, z print("unreachable prior collection: %s" % gc.collect()) print("unreachable after collection: %s" % len(gc.garbage)) print("WithDel objects count: %s" % objgraph.count('WithDel'))
def circle_quote(): # 循环引用 class Dog: pass class Person(): pass p = Person() d = Dog() print(objgraph.count("Person")) print(objgraph.count("Dog")) p.pet = d d.master = p # 删除 p, d之后, 对应的对象是否被释放掉 del p del d print(objgraph.count("Person")) print(objgraph.count("Dog"))
def process_garbage(label=''): """Perform garbage collection and report uncollectable objects. This function does nothing if DEBUG2 is not enabled for this module. If DEBUG3 is enabled, print a summary of the uncollectable objects. The references in gc.garbage are deleted so as to rebuild the garbage list on subsequent calls. The label argument is used solely for logging, and may be left undefined to print a generic message. """ if LOG.isEnabledFor(logging.DEBUG2): ct = gc.get_count() LOG.debug2("gc.get_count() => {}, {}, {}".format(ct[0], ct[1], ct[2])) LOG.debug2("collecting garbage {}...".format(label)) # Note that any weak references will likely be purged as a result. gc.collect() LOG.debug2("{} uncollectable garbage objects".format(len(gc.garbage))) try: if LOG.isEnabledFor(logging.DEBUG3) and _Pympler: _log_summary(gc.garbage) finally: # Clear references to the garbage del gc.garbage[:] if LOG.isEnabledFor(logging.DEBUG3) and _ObjGraph: # Have to get the objects ourselves and free them, otherwise count() leaks. all_objects = gc.get_objects() try: types = [ 'Assign', 'Branch', 'CommitChange', 'ObjectType', 'ObjectTypeList' ] for o_type in types: count = objgraph.count(o_type, all_objects) LOG.debug3("objgraph.count: {} {} objects".format( count, o_type)) finally: del all_objects
# print('inside_1', objgraph.count('A')) # print('inside_1', objgraph.count('B')) def test2(): a = A() b = B() a.child = b b.parent = a # print('inside_2', objgraph.count('A')) # print('inside_2', objgraph.count('B')) test1() # 对象应用已经回收 print('outside1_2', objgraph.count('A')) print('outside1_2', objgraph.count('B')) test2() # 存在循环引用未被回收 # gc.collect() print('Object count of A:', objgraph.count('A')) print('Object count of B:', objgraph.count('B')) print(gc.isenabled()) objgraph.show_backrefs(objgraph.by_type('A'), max_depth=10, filename='obj_A.png') # ... run your application ... tracemalloc.start() test2()
import objgraph class Person1: pass class Dog: pass p = Person1() d = Dog() print(objgraph.count("Person1")) print(objgraph.count("Dog")) p.pet = d d.master = p # 删除 p, d之后, 对应的对象是否被释放掉 del p del d print(objgraph.count("Person1")) print(objgraph.count("Dog")) print( "---------------------------------垃圾回收机制-分代回收---------------------------------------" )
gc.disable() class A(object): pass class B(object): pass def test1(): a = A() b = B() test1() print objgraph.count('A') print objgraph.count('B') def test2(): a = A() b = B() a.child = b b.parent = a test2() print 'Object count of A:', objgraph.count('A') print 'Object count of B:', objgraph.count('B') gc.collect() print 'Object count of A:', objgraph.count('A') print 'Object count of B:', objgraph.count('B')
def func () : js1 = saga.job.Service ('ssh://localhost/bin/sh') ## js0 = saga.job.Service ('ssh://localhost/bin/sh') ## t0 = saga.job.Service.create ('ssh://localhost/bin/sh') ## t0.wait () ## js0 = t0.get_result () ## print js0.url print "--------------------------" func () print "--------------------------" gc.collect () # print "==============================" # for g in gc.garbage : # print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" # pp (g) # print "==============================" # pp (gc.garbage) # print "==============================" # checks.show_backrefs (js1._adaptor) print checks.count('ShellJobService') checks.show_backrefs(checks.by_type('ShellJobService')[-1])
pass def func_to_leak(): o = OBJ() _cache.append(o) # do something with o, then remove it from _cache if True: # this seem ugly, but it always exists return _cache.remove(o) if __name__ == '__main__': print(type(func_to_leak)) print('counter OBJ:', objgraph.count('OBJ')) print('counter func_to_leak:', objgraph.count('function')) objgraph.show_growth() try: func_to_leak() except: pass print('after call func_to_leak') # 统计该类型对象的数目 print('counter OBJ:', objgraph.count('OBJ')) print('counter func_to_leak:', objgraph.count('function')) # 更具对象类型返回对象列表 print('999999999', objgraph.by_type('str')) # 打印实例化做多的前10个对象 print(objgraph.show_most_common_types(10)) # 统计自上次调用以来增加得最多的对象,这个函数非常有利于发现潜在的内存泄露
返回Python垃圾回收器正在跟踪的对象个数. Python有两种共存的内存管理机制: 引用计数和垃圾回收. 引用计数是一种非常高效的内存管理手段, 当一个Python对象被引用时其引用计数增加1, 当其不再被一个变量引用时则计数减1. 当引用计数等于0时对象被删除 """ import gc import objgraph gc.disable() class A(object): pass class B(object): pass def test1(): a = A() b = B() test1() print("Object count of A:", objgraph.count('A')) print("Object count of B:", objgraph.count('B'))
#python 使用引用计数器机制、“标记-清除”和垃圾回收机制并存。计数器机制无法解决循环引用的问题,垃圾回收机制可以 import gc import weakref #------------自动回收----------- print(gc.isenabled()) #查看垃圾自动回收机制是否开启 print( gc.get_threshold() ) #查看当前机制的默认参数,返回元组(700,10,10):新增对象个数-消亡对象个数 达到700触发,0代触发10次则触发0代和1代的检测,1代触发10次,会触发0代、1代和2代的检测 #-----------手动回收------------- import objgraph class Person: pass class Dog: pass p = Person() d = Dog() p.pet = d d.master = p #创造了一个循环引用,以后写代码的时候开业通过弱引用来规避循环引用,d.master = weakref.ref(p) 弱引用,不会造成计数器增减 del p del d gc.collect() #参数不写,则回收所有代的垃圾 print(objgraph.count('Person')) #打印Person类产生的对象有多少个 print(objgraph.count('Dog'))
#!/usr/bin/env python # coding=utf-8 # 演示循环引用 import objgraph # 可以用来检测内存泄漏 if __name__ == '__main__': a = list() b = list() # 查看list类型对象的数量 # output: n print(objgraph.count('list')) a.append(b) # b.append(a) # 循环引用 print(a) print(b) del a del b # 再次查看list类型对象的数量 # output: n print(objgraph.count('list'))
# gc.set_debug (gc.DEBUG_LEAK | gc.DEBUG_STATS) def func(): js1 = saga.job.Service('ssh://localhost/bin/sh') ## js0 = saga.job.Service ('ssh://localhost/bin/sh') ## t0 = saga.job.Service.create ('ssh://localhost/bin/sh') ## t0.wait () ## js0 = t0.get_result () ## print js0.url print "--------------------------" func() print "--------------------------" gc.collect() # print "==============================" # for g in gc.garbage : # print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" # pp (g) # print "==============================" # pp (gc.garbage) # print "==============================" # checks.show_backrefs (js1._adaptor) print checks.count('ShellJobService') checks.show_backrefs(checks.by_type('ShellJobService')[-1])
# Time: 2020/8/20 19:53 # ------------------------------------------------------------------------------- import sys import objgraph import gc if __name__ == '__main__': class Person: pass class Dog: pass p = Person() d = Dog() p.pet = d d.master = p print(sys.getrefcount(p)) print(sys.getrefcount(d)) del p del d gc.collect() # 手动触发垃圾回收 print(objgraph.count("Person")) print(objgraph.count("Dog"))
def test_long_type_names(self): x = type('MyClass', (), {'__module__': 'mymodule'})() # noqa y = type('MyClass', (), {'__module__': 'other'})() # noqa self.assertEqual(2, objgraph.count('MyClass')) self.assertEqual(1, objgraph.count('mymodule.MyClass'))
tr.print_diff() #p = pstats.Stats('vslib.profile') #p.sort_stats('cumulative').print_stats(20) if 0: objects = muppy.get_objects(include_frames=True) print muppy.get_size(objects) sum1 = summary.summarize(objects) summary.print_(sum1) if 0: root = '' ib = refbrowser.InteractiveBrowser(root) ib.main() if 1: import objgraph, inspect objgraph.show_most_common_types(limit=30) if objgraph.count('document') > 0: print 'document:', objgraph.count('document') docs = objgraph.by_type('document') d = docs[0] objgraph.show_backrefs(docs, max_depth=10) #chain = objgraph.find_backref_chain(d, inspect.ismodule) #in_chain = lambda x, ids=set(map(id, chain)): id(x) in ids #objgraph.show_backrefs(chain[-1], len(chain), filter=in_chain) #print 'document n: %d' % objgraph.count('document') #print 'section n: %d' % objgraph.count('section') #import pdb; pdb.set_trace()
import objgraph, gc, weakref gc.disable() class Person: def __del__(self): print('person clear') class Dog: def __del__(self): print('dog clear') p = Person() d = Dog() p.pet = weakref.ref(d) d.master = weakref.ref(p) print(objgraph.count('Person')) print(objgraph.count('Dog')) del p del d # gc.collect() print(objgraph.count('Person')) print(objgraph.count('Dog')) # weakref.WeakKeyDictionary()
print(gc.get_threshold()) class Persion(): pass class Cat(): pass p = Persion() c = Cat() p.name = 'sudan' p.pet = c c.master = p print(sys.getrefcount(p)) print(sys.getrefcount(c)) del c del p # 进行手动 gc gc.collect(objgraph.count('Persion')) gc.collect(objgraph.count('Cat'))