每个请求的django.dispatch.saferef.BoundMethodWeakRef对象泄漏导致内存泄漏

时间:2014-05-03 18:34:43

标签: django memory-leaks guppy

django webapp正在泄漏内存。我在这里尝试了一些建议:https://docs.djangoproject.com/en/dev/faq/models/#why-is-django-leaking-memory即使该应用不是独立的。

我使用guppy(通过这个漂亮的页面:http://www.smira.ru/wp-content/uploads/2011/08/heapy.html)来分析堆,我看到请求与django.dispatch.saferef.BoundMethodWeakRef对象泄漏之间存在关联:

Partition of a set of 146642 objects. Total size = 10765760 bytes.
 Index  Count   %     Size   % Cumulative  % Referrers by Kind (class / dict of class)
     0  49064  33  2914412  27   2914412  27 types.CodeType
     1  21631  15   737184   7   3651596  34 tuple
     2  12883   9   727296   7   4378892  41 function
     3   5505   4   583728   5   4962620  46 dict of module
     4   3163   2   497232   5   5459852  51 type
     5   8192   6   481600   4   5941452  55 dict of type
     6    328   0   424000   4   6365452  59 function, module
     7    775   1   403000   4   6768452  63 django.dispatch.saferef.BoundMethodWeakref
     8   1597   1   351728   3   7120180  66 function, tuple
     9   6015   4   270704   3   7390884  69 dict (no owner)
<1864 more rows. Type e.g. '_.more' to view.>
Reference Pattern by <[dict of] class>.
 0: _ --- [-] 775 (<referred by: <Nothing>> | <referred by: django.dispatch.s...
 1: a      [-] 774 django.dispatch.saferef.BoundMethodWeakref: 0x84696cc...
 2: aa ---- [-] 1549 tuple: 0x846908c*1, 0x846910c*2, 0x846920c*1...
 3: a3       [-] 774 function: django.dispatch.saferef.remove...
 4: a4 ------ [-] 1548 __builtin__.weakref: 0x847539c, 0x8475a04, 0x8475b44...
 5: a5         [-] 774 dict of django.dispatch.saferef.BoundMethodWeakref: 0x...
 6: a6 -------- [^ 1] 774 django.dispatch.saferef.BoundMethodWeakref: 0x84696...
 7: aab      [-] 3 list: 0xb6e7156cL*1, 0xb6e7168cL*773, 0xb701684cL*2
 8: aaba ---- [-] 3 dict of django.dispatch.dispatcher.Signal: 0xb6ee1c6cL...
 9: aabaa      [-] 3 django.dispatch.dispatcher.Signal: 0xb6ee1c6cL...
<Type e.g. '_.more' for more.>
10: aaba3 ----- [S] 3 dict of module: ..models, ..signals, ..signals
11: aabaab      [-] 3 types.MethodType: <django.dispatch.dispatcher.Signal at...
12: aabaaba ---- [-] 2 list: 0xa12888c*1, 0xa13896c*1
13: aabaabaa      [-] 2 dict of django.dispatch.saferef.BoundMethodWeakref: 0...
14: aabaaba3 ----- [-] 2 django.dispatch.saferef.BoundMethodWeakref: 0x9e9f46...
15: aabaaba4        [-] 5 tuple: 0xa15154c*1, 0xa15186c*2, 0xa1531ac*2...
16: aabaaba5 ------- [^ 7] 3 list: 0xb6e7156cL*1, 0xb6e7168cL*773...
17: aabaaba4b        [-] 2 function: django.dispatch.saferef.remove...
18: aabaaba4ba ------ [-] 4 __builtin__.weakref: 0x98e90cc, 0x98e9734...
19: aabaaba4baa        [^ 13] 2 dict of django.dispatch.saferef.BoundMethodWe...

请注意,django.dispatch.saferef.BoundMethodWeakref会在每个请求的计数(此处为775)中上升。

我对django不熟悉,但我认为在这个应用程序中做了不同的事情是使用自定义中间件类向process_request中的每个请求对象添加对象和标志的引用。我不确定引用是否导致django不以某种方式释放请求的资源。

以下是引用和标志上的代码标记:

class ApplianceMiddleware(object):

    def process_request(self, request):
    request.__class__.appliance = get_appliance()
    # do heap analysis across requests to check for memory leaks - heap
    # size across requests should be constant
    heap_analysis.analyse()

    request.__class__.from_int_if = False

    # Continue processing
    return None

有谁知道造成这种情况的原因是什么?如果将引用添加到导致此问题的请求中,我可以在哪里清理?也许通过保留对请求对象的引用并在处理下一个请求时删除对设备对象的引用?

1 个答案:

答案 0 :(得分:0)

事实证明,有一些信号处理程序正在注册request_finish,post_save和post_modify。他们为每个请求进行了“连接”,之后他们就一直坚持下去。处理信号时断开连接解决了内存泄漏问题。

它与信号有关的线索在堆积信息中。 e.g:

aabaa      [-] 3 django.dispatch.dispatcher.Signal: 0xb6ee1c6cL...
10: aaba3 ----- [S] 3 dict of module: ..models, ..signals, ..signals