【问题标题】:Debugging memory leak in Python service that uses Redis pub/sub在使用 Redis pub/sub 的 Python 服务中调试内存泄漏
【发布时间】:2015-02-02 09:23:40
【问题描述】:

我正在尝试使用 Redis 发布/订阅功能构建 Python 2.7 服务。我在 Ubuntu 12.04 上使用 redis 2.8.17 和 redis-py 2.10.3 作为客户端。不幸的是,我的服务似乎正在泄漏内存。内存消耗似乎随着服务接收/使用/处理的消息数量呈线性增加。

我尝试使用工具memory_profiler 通过装饰我的主订阅循环来调试它。为了让它连续打印输出,我将其更改为每收到一百条消息就退出。输出如下所示:

Line #    Mem usage    Increment   Line Contents
================================================
    62     39.3 MiB      0.0 MiB       @memory_profiler.profile
    63                                 def _listen(self, callback):
    64     40.1 MiB      0.7 MiB           for _ in self.redis_pubsub.listen():
    65     40.1 MiB      0.0 MiB               self.count += 1
    66     40.1 MiB      0.0 MiB               self._consume(callback)
    67     40.1 MiB      0.0 MiB               if self.count == 100:
    68     40.1 MiB      0.0 MiB                   self.count = 0
    69     40.1 MiB      0.0 MiB                   break
    70     40.1 MiB      0.0 MiB           gc.collect()

它报告每推送到服务的每 100 条消息都会出现类似的增长。回调是实际执行应用程序的函数,所以如果我的应用程序代码有问题,我实际上希望在第 65 行增加内存..

输出让我怀疑是 redis 客户端,所以我还使用 pympler.asizeof 检查了 self.redis_pubsub 和 redis.StrictRedis 对象的大小。这些对象一开始很小,并且在服务接收消息时根本不会增加。

此外,当尝试使用 pympler.muppy 和 pympler.summarize 查找泄漏对象时,它不会报告任何不断增长的对象计数或内存累积。此外,内存消耗和增长的总数与 Linux 中 top 提供的数字不同。

我被卡住了,有没有人知道可能发生了什么或对如何进一步调试有任何想法?

【问题讨论】:

  • 你确定你有内存泄漏吗?这有什么证据?
  • 好问题。如果我继续生成消息几个小时,内存不会被回收到至少 500MB(我应该测试直到我用完)。我在最后用 gc.collect() 更新了我的示例,以表明我至少不能强制它。
  • 坦率地说,我无法理解为什么 redis 客户端应该使用 700KB 的内存来接收 100 条消息。或者,如果我从 memory_profile 数据中得出结论,因为我不知道该工具是如何工作的,所以该数据没有根据并且是错误的。
  • 很抱歉,我不是 pympler 专家,无法为您提供更多帮助。但是我 20 年以来在捕获内存泄漏方面的经验让我开始关注top 或其他间接系统测量内存泄漏:在释放内存之前尝试了解所有高层做什么是非常痛苦的,这会成为一个真正的迷宫对于使用像 python 这样的垃圾收集器引擎的语言。我的建议是尝试通过一些简单的例子来很好地理解这个工具,然后相信它,如果有的话,你可以找到内存泄漏的证据。看看objgraph,它可以帮助你。

标签: python python-2.7 memory-leaks redis redis-py


【解决方案1】:

我花了几个小时在pub/sub 设置中调试同样的问题。确实存在内存泄漏,我在发布消息时找不到避免它的方法。我的转变是使用multiprocessing 在单独的进程上运行发布部分。这对我很有用,因为我每隔几秒就会发布一次消息,所以这是一个合理的权衡。

一个没有泄漏的替代方法是tornadis

【讨论】:

    猜你喜欢
    • 2022-06-22
    • 2011-06-22
    • 1970-01-01
    • 2021-01-10
    • 2010-11-23
    • 2013-09-28
    • 1970-01-01
    • 1970-01-01
    • 2011-11-19
    相关资源
    最近更新 更多