我正在分析我的扭曲服务器。它使用的内存比我预期的多得多。它的内存使用量随着时间的推移而增长。
ps -o pid,rss,vsz,sz,size,command
PID RSS VSZ SZ SZ COMMAND
7697 70856 102176 25544 88320 twistd -y broadcast.tac
正如您所看到的,其成本 102176 KB ,即 99.78125 MB 。我使用扭曲的沙井中的孔雀鱼来观察内存使用情况。
>>> hp.heap()
Partition of a set of 120537 objects. Total size = 10096636 bytes.
Index Count % Size % Cumulative % Kind (class / dict of class)
0 61145 51 5309736 53 5309736 53 str
1 27139 23 1031596 10 6341332 63 tuple
2 2138 2 541328 5 6882660 68 dict (no owner)
3 7190 6 488920 5 7371580 73 types.CodeType
4 325 0 436264 4 7807844 77 dict of module
5 7272 6 407232 4 8215076 81 function
6 574 0 305776 3 8520852 84 dict of class
7 605 1 263432 3 8784284 87 type
8 602 0 237200 2 9021484 89 dict of type
9 303 0 157560 2 9179044 91 dict of zope.interface.interface.Method
<384 more rows. Type e.g. '_.more' to view.>
嗯......好像有什么不对劲。 Guppy显示内存的总使用量为10096636字节,即 9859.996 KB 或 9.628 MB 。
这是一个巨大的差异。这个奇怪的结果出了什么问题?我做错了什么?
更新 我昨晚写了一个监视器脚本。它记录内存使用情况和在线用户数。它是一个无线电服务器,所以你可以看到有无线电和全部听众。这是我通过matplotlib生成的图。
有点奇怪。有时ps打印的内存使用率非常低,如此2010-01-15 00:46:05,139 INFO 4 4 17904 36732 9183 25944
2010-01-15 00:47:03,967 INFO 4 4 17916 36732 9183 25944
2010-01-15 00:48:04,373 INFO 4 4 17916 36732 9183 25944
2010-01-15 00:49:04,379 INFO 4 4 17916 36732 9183 25944
2010-01-15 00:50:02,989 INFO 4 4 3700 5256 1314 2260
内存使用超低值的原因是什么?而且,即使没有在线无线电,也没有听众,内存使用量仍然很高。
答案 0 :(得分:6)
可能是由于交换/内存预留,基于ps的定义:
RSS: resident set size, the non-swapped physical memory
that a task has used (in kiloBytes).
VSZ: virtual memory usage of entire process.
vm_lib + vm_exe + vm_data + vm_stack
它可能有点令人困惑,可以看到4个不同大小的指标:
# ps -eo pid,vsz,rss,sz,size,cmd|egrep python
PID VSZ RSS SZ SZ CMD
23801 4920 2896 1230 1100 python
虚拟大小包括由进程保留但未使用的内存,已加载的所有共享库的大小,已换出的页面以及已由您的进程释放的块,因此它可能更大而不是python中所有活动对象的大小。
一些调查内存性能的其他工具:
Heapy(你正在使用的Guppy的一部分): http://guppy-pe.sourceforge.net/
Python内存验证器 http://www.softwareverify.com/python/memory/index.html
PySizer http://pysizer.8325.org/
使用pdb和objgraph跟踪内存泄漏的良好指南:
http://www.lshift.net/blog/2008/11/14/tracing-python-memory-leaks
答案 1 :(得分:3)
如上所述,RSS大小是您最感兴趣的。 “虚拟”大小包括映射库,您可能不想计算它们。
自从我使用heapy以来已经有一段时间了,但我很确定它打印的统计数据不包括heapy本身添加的开销。这个开销可能非常重要(我已经看到100MB的RSS进程再增加了十几个MB,请参阅http://www.pkgcore.org/trac/pkgcore/doc/dev-notes/heapy.rst)。
但在你的情况下,我怀疑问题是你正在使用一些C库,它们以一种堆不能跟踪的方式泄漏或使用内存。 Heapy知道python对象直接使用的内存,但如果这些对象包装单独分配的C对象,则通常根本不知道该内存。您可能能够为绑定添加大量支持(但如果您不控制您使用的绑定,那显然很麻烦,即使您控制绑定,您也可能无法执行此操作,具体取决于您要包装的内容)。
如果在C级存在泄漏,那么堆也将失去对该内存的跟踪(RSS大小将会增加,但是堆积的报告大小将保持不变)。 Valgrind可能是跟踪这些问题的最佳选择,就像在其他C应用程序中一样。
最后:内存碎片通常会导致内存使用率(如上图所示)上升但不会下降(很多)。守护进程通常没有那么大的问题,因为进程将重用这个内存,它只是不会释放回os,所以top中的值不会再回落。如果内存使用量(如上图所示)与用户数(连接数)或多或少呈线性上升,则不会再次下降,但在您达到新的最大用户数之前也不会永远增长,可能是碎片化责怪。
答案 2 :(得分:1)
这不是一个完整的答案,但是从你的沙井,我还建议在用ps或top查看之前手动运行gc.collect()。 guppy将显示已分配的堆,但不会做任何事情来主动释放不再分配的对象。