python - 如何找到扭曲服务器内存使用量增加的根源?

标签 python memory-leaks memory-management twisted

我有一个用 Python 编写并基于 Twisted 的音频广播服务器。它工作正常,但是当服务器上有更多用户时,它的内存使用量会增加,但是当这些用户下线时,内存使用量永远不会下降。如下图所示: alt text

你可以看到监听器/ radio 的曲线上升的地方内存使用曲线上升,但是监听器/ radio 的峰值之后,内存使用率仍然很高,从来没有下降过。

我尝试了以下方法来解决这个问题:

  1. 将 Twisted 从 8.2 升级到 9.0
  2. 使用 guppy 倾倒大量食物,但完全没有帮助
  3. 将 selector reactor 切换到 epoll reactor,同样的问题。
  4. 使用 objgraph 绘制对象关系图,但我看不到点。

这是我用来运行我的扭曲服务器的环境:

  • Python:2.5.4 r254:67916
  • 操作系统:Linux 版本 2.6.18-164.9.1.el5PAE (mockbuild@builder16.centos.org)(gcc 版本 4.1.2 20080704 (Red Hat 4.1.2-46))
  • Twisted:9.0(在 virtualenv 下)

孔雀鱼的垃圾场:

Partition of a set of 116280 objects. Total size = 9552004 bytes.
 Index  Count   %     Size   % Cumulative  % Type
  0  52874  45  4505404  47   4505404  47 str
  1   5927   5  2231096  23   6736500  71 dict
  2  29215  25  1099676  12   7836176  82 tuple
  3   7503   6   510204   5   8346380  87 types.CodeType
  4   7625   7   427000   4   8773380  92 function
  5    672   1   292968   3   9066348  95 type
  6    866   1    82176   1   9148524  96 list
  7   1796   2    71840   1   9220364  97 __builtin__.weakref
  8   1140   1    41040   0   9261404  97 __builtin__.wrapper_descriptor
  9   2603   2    31236   0   9292640  97 int

可以看到,总大小9552004字节为9.1 MB,可以看到ps命令报告的rss:

[xxxx@webxx ~]$ ps -u xxxx-o pid,rss,cmd
  PID   RSS CMD
22123 67492 twistd -y broadcast.tac -r epoll

我的服务器的rss是65.9 MB,这意味着我的服务器中有56.8 MB不可见的内存使用,它们是什么?

我的问题是:

  1. 如何找到内存使用量增加的原因?
  2. 什么是 guppy 可见的内存使用情况?
  3. 那些不可见的内存使用是什么?
  4. 是不是某些 C 语言模块的内存泄漏造成的?如果是,我该如何追踪和修复它?
  5. Python 如何管理内存?内存池?我认为这可能是由音频数据 block 引起的。这样在 Python 解释器拥有的内存块中几乎没有泄漏。

2010/1/20 更新: 有趣的是,我下载了最新的日志文件,它显示内存从不增加。我认为可能是分配的内存空间足够大。这是最新的数字。 alt text

2010/1/21 更新: 这里的另一个数字。嗯....提高一点 alt text

糟糕...仍在上升 alt text

最佳答案

正如我的猜测,这是由于内存碎片问题。最初的设计是将音频数据 block 保存在一个列表中,它们都不是固定大小的。一旦缓冲列表的总大小超过缓冲区的限制,它会从列表顶部弹出一些 block 来限制大小。它可能看起来像这样:

  1. block 大小 511
  2. block 大小 1040
  3. block 大小 386
  4. block 大小 1350
  5. ...

大部分大于 256 字节,Python 使用 malloc 处理大于 256 字节的 block ,而不是使用内存池。你可以想象那些 block 被分配和释放,会发生什么?例如,当释放大小为 1350 的 block 时,堆中可能有 1350 字节的空闲空间。之后又来了一个请求 988,一旦 malloc 捡到了这个洞,然后又多了一个大小为 362 的新的小空洞。经过长时间的运行,堆里的小洞越来越多,也就是说,有这么多堆中的许多碎片。虚拟内存的页面大小通常为 4KB,这些碎片分布在大范围的堆周围,这使得操作系统无法将这些页面交换出去。因此,RSS 总是很高。

我的服务器的音频 block 管理模块的设计修改后,现在它使用的内存很少。您可以看到该图并与上一个进行比较。

alt text

新设计使用字节数组而不是字符串列表。这是一大块内存,所以没有更多的碎片。

关于python - 如何找到扭曲服务器内存使用量增加的根源?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2100192/

相关文章:

Java - 是否有一种线程安全的方式来分配新对象而无需锁?

R 的保留内存是已分配数组大小的两倍

python - 如何在 pandas DataFrame 中设置给定索引级别的值

python - 在 Pandas 中检索数据

Python WWS 库需要整个证书链来验证服务器

ios - 导航堆栈中的ViewController在弹出时不会取消初始化,导致内存泄漏

python - 从 Python/Pandas Dataframe 的列表列中的列表中删除空格或 NaN

iphone - 根据仪器显示,WebView 似乎正在泄漏。通用Block-56

C# - 试图找到剩余的 EventHandler 以防止控制超出范围

java - 尝试在我的 java swing 代码中查找内存泄漏