【问题标题】:The memory usage reported by guppy differ from ps commandguppy 报告的内存使用情况与 ps 命令不同
【发布时间】:2010-01-14 17:54:07
【问题描述】:

我正在分析我的扭曲服务器。它使用的内存比我预期的要多得多。它的内存使用量会随着时间的推移而增长。

 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 KBs9.628 MBs

这是一个巨大的差异。这个奇怪的结果有什么问题?我做错了什么?

更新: 我昨晚写了一个监控脚本。它记录了内存使用情况和在线用户数。它是一个广播服务器,因此您可以看到有广播和总听众。这是我用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

内存使用率超低的原因是什么?而且,即使没有在线电台,没有听众,内存使用率仍然很高。

【问题讨论】:

    标签: python memory-management twisted guppy


    【解决方案1】:

    可能是由于交换/内存预留,基于 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 中所有活动对象的大小。

    一些额外的工具来调查内存性能:

    使用 pdb 和 objgraph 在 python 中跟踪内存泄漏的好指南:

    http://www.lshift.net/blog/2008/11/14/tracing-python-memory-leaks

    【讨论】:

    • 但即使我将 69 MB 与 10 MB 进行比较,也太过分了。可能是什么问题呢?更重要的是,内存使用量随着时间的推移而增长。一开始,RSS 大约是 2xMB,现在是 6x。
    • guppy 报告的一些对象可能会被换出,因此 python 可能会报告这些对象,而 rss 不会包含它。我不确定为什么该进程保留了这么多内存,也许是吨共享库..?
    • 所有库在启动时加载。服务器启动时,它在 RSS 字段中仅使用 2x MB。库占用额外的内存使用是没有意义的。有什么方法可以知道那些不可见的内存使用情况是什么?
    • hmm,听起来好像是在某个地方泄漏了内存,您可以尝试使用 Python Memory Validator 来确定哪个代码分配的内存最多?
    【解决方案2】:

    如上所述,RSS 大小是您最感兴趣的。 “虚拟”大小包括映射库,您可能不想计算在内。

    自从我使用 heapy 已经有一段时间了,但我很确定它打印的统计数据不包括 heapy 本身增加的开销。这种开销可能相当大(我已经看到一个 100MB 的 RSS 进程又增长了十几个 MB,请参阅 http://www.pkgcore.org/trac/pkgcore/doc/dev-notes/heapy.rst)。

    但在您的情况下,我怀疑问题在于您正在使用一些 C 库,该库以 heapy 无法跟踪的方式泄漏或使用内存。 Heapy 知道 python 对象直接使用的内存,但是如果这些对象包装了单独分配的 C 对象,heapy 通常根本不知道该内存。您可能能够为您的绑定添加大量支持(但如果您不控制所使用的绑定,这显然是一件麻烦事,即使您确实控制了绑定,您也可能无法做到这一点,具体取决于您包装的内容)。

    如果 C 级别存在泄漏,heapy 也会失去对该内存的跟踪(RSS 大小会增加,但 heapy 报告的大小将保持不变)。 Valgrind 可能是您追踪这些的最佳选择,就像在其他 C 应用程序中一样。

    最后:内存碎片通常会导致您的内存使用量(如上图所示)上升但不会下降(很多)。对于守护进程,这通常不是什么大问题,因为进程将重用此内存,它只是没有释放回操作系统,因此顶部的值不会下降。如果内存使用量(如上图所示)随着用户数(连接数)或多或少呈线性上升,不会回落,但在达到新的最大用户数之前也不会永远增长,碎片可能是责备。

    【讨论】:

      【解决方案3】:

      这不是一个完整的答案,但是从您的沙井来看,我还建议在使用 ps 或 top 查找之前手动运行 gc.collect()。 guppy 将显示分配的堆,但不会主动释放不再分配的对象。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-03-23
        • 2015-02-27
        • 1970-01-01
        • 2015-07-02
        • 2018-03-22
        • 2016-12-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多