我的应用程序中有一个类,在实例化之后,永远不会被垃圾回收。怎么会这样?
到目前为止,我已经排除了:
gc.garbage
为空,不应该是图表中__del__
的任何内容;请参阅下面的测试)gc.collect()
,直到它返回0
)有问题的类是应用程序中的核心业务逻辑模型之一, 实例中有大量的引用循环(recalculate()
方法创建一个循环图〜数百个节点),但应该直接收集垃圾收集器。
原来如此!我错过了什么?这个班级的未被引用的实例怎么可能活着?
更新:来自sys.getrefcount(…) = 16
的引用次数大于len(gc.get_referrers(…)) = 15
,因此必须有gc
之外的引用(感谢您的建议,{ {3}})
显示泄漏的测试用例:
import gc
import weakref
import objgraph
from myapp import BusinessClass
def find_live_objects(cls):
""" Returns all live objects of type ``cls``. """
return [
weakref.ref(o)
for o in gc.get_objects()
if type(o) == cls
]
def test():
# Load and delete a similar object in case there are
# and class-specific caches hiding somewhere.
# Note: the results are the same without this.
a = BusinessClass.objects.get(id=1)
a.recalculate()
del a
# Snapshot all live objects
live_now = list(gc.get_objects())
live_set = set(id(x) for x in live_now)
print "Live objects:", len(live_set)
# Create and delete the object we're interested in
a = BusinessClass.objects.get(id=2)
a.recalculate()
del a
print "gc:", gc.collect()
print "gc:", gc.collect()
print "gc:", gc.collect()
print "Garbage:", gc.garbage
live_list = find_live_objects(BusinessClass)
print "Found:", [x() for x in live_list]
live = live_list[1]
print "Searching for:", live()
chain = objgraph.find_backref_chain(
live(),
(lambda x: id(x) in live_set),
max_depth=999999,
)
print "Chain:", chain
test()
跑步时:
$ python find-leaks.py
Live objects: 132062
gc: 21
gc: 0
gc: 0
Garbage: []
Found: [BusinessClass(id=1), BusinessClass(id=2)]
Searching for: BusinessClass(id=2)
Chain: [BusinessClass(2)]
请注意,找不到任何活动对象的背景。
版本信息:
$ python Python 2.7.10 (default, Jul 14 2015, 19:46:27) [GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.39)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import django >>> django.VERSION (1, 6, 11, 'final', 0)