我有一个在uwsgi下运行的django webserver似乎泄漏了内存。
具体来说,进程的RSS会慢慢增长,直到最终我必须重新启动它。
我知道其他类似的问题,但到目前为止找到的所有解决方案/结论似乎都不适用(我能找到)。
到目前为止,我已使用meliae,Heapy,pympler和objgraph来检查python堆,它们都报告相同的事情:使用正常的堆大约40MB的内存(预期),随着时间的推移变化非常小(根据需要)。
遗憾的是,这与RSS进程完全不一致,在python堆大小中, no 反射将很快增长到400MB +。
一些示例输出来说明我的观点 -
pympler输出比较python堆/对象内存与进程RSS:
Memory snapshot:
types | # objects | total size
============================================= | =========== | ============
dict | 20868 | 19852512
str | 118598 | 11735239
unicode | 19038 | 10200248
tuple | 58718 | 5032528
type | 1903 | 1720312
code | 13225 | 1587000
list | 11393 | 1289704
datetime.datetime | 6953 | 333744
int | 12615 | 302760
<class 'django.utils.safestring.SafeUnicode | 18 | 258844
weakref | 2908 | 255904
<class 'django.db.models.base.ModelState | 3172 | 203008
builtin_function_or_method | 2612 | 188064
function (__wrapper__) | 1469 | 176280
cell | 2997 | 167832
getset_descriptor | 2106 | 151632
wrapper_descriptor | 1831 | 146480
set | 226 | 143056
StgDict | 217 | 138328
---------------------------
Total object memory: 56189 kB
Total process usage:
- Peak virtual memory size: 549016 kB
- Virtual memory size: 549012 kB
- Locked memory size: 0 kB
- Peak resident set size: 258876 kB
- Resident set size: 258868 kB
- Size of data segment: 243124 kB
- Size of stack segment: 324 kB
- Size of code segment: 396 kB
- Shared library code size: 57576 kB
- Page table entries size: 1028 kB
---------------------------
Heapy输出显示类似的内容
Memory snapshot:
Partition of a set of 289509 objects. Total size = 44189136 bytes.
Index Count % Size % Cumulative % Kind (class / dict of class)
0 128384 44 12557528 28 12557528 28 str
1 61545 21 5238528 12 17796056 40 tuple
2 5947 2 3455896 8 21251952 48 unicode
3 3618 1 3033264 7 24285216 55 dict (no owner)
4 990 0 2570448 6 26855664 61 dict of module
5 2165 1 1951496 4 28807160 65 type
6 16067 6 1928040 4 30735200 70 function
7 2163 1 1764168 4 32499368 74 dict of type
8 14290 5 1714800 4 34214168 77 types.CodeType
9 10294 4 1542960 3 35757128 81 list
<1046 more rows. Type e.g. '_.more' to view.>
---------------------------
Total process usage:
- Peak virtual memory size: 503132 kB
- Virtual memory size: 503128 kB
- Locked memory size: 0 kB
- Peak resident set size: 208580 kB
- Resident set size: 208576 kB
- Size of data segment: 192668 kB
- Size of stack segment: 324 kB
- Size of code segment: 396 kB
- Shared library code size: 57740 kB
- Page table entries size: 940 kB
---------------------------
请注意,在这两种情况下,报告的堆大小为40-50MB,而进程RSS为200MB +。
我还使用了objgraph的 get_leaking_objects()来尝试查看C扩展是否进行了错误的引用计数,但是非gc'able对象的数量并没有显着增长
有没有人对如何进行调试有任何见解?在这一点上,我假设有以下两种情况之一:
值得一提的是,我在任何一种开发环境中都没有成功复制它(虽然我可能不会给它们投入足够的流量)。
我们确实使用了一堆具有C扩展名的模块(simplejson,hiredis等),所以它们确实可以说是原因。
寻找跟踪此问题的方法。
答案 0 :(得分:2)
您使用的是哪个版本的Python?在Python 2.4中,Python内存分配器没有将内存返回给操作系统。
仍然在较新的版本中,你可以看到一个问题,它与Python的内存分配器有关,它保留了释放的简单类型列表,或者你在Linux上运行的问题是glibc的malloc实现如何从操作系统分配内存的内在问题。请查看http://effbot.org/pyfaq/why-doesnt-python-release-the-memory-when-i-delete-a-large-object.htm和http://pushingtheweb.com/2010/06/python-and-tcmalloc/。