实时监控Python web 应用的内存使用量

Python部落组织翻译,禁止转载,欢迎转发


前段时间我在做一个Python web应用,在产品线上跟内存占用太大的问题纠结,最后终于找到一个解决这个问题的技术:就是在应用运行时增加一个简单的能够暴露内存统计的API.

采用Pympler


在CPython中有个很棒的内存统计调试模块叫Pympler(https://pythonhosted.org/Pympler/).他能walk你的进程堆,并报告所有Python分配对象的类型,个数和以bytes单位的大小.


下面这个函数就是用Pympler生成并返回内存总结的字符串:


def memory_summary():
    # Only import Pympler when we need it. We don't want it to
    # affect our process if we never call memory_summary.
    from pympler import summary, muppy
    mem_summary = summary.summarize(muppy.get_objects())
    rows = summary.format_(mem_summary)
    return '\n'.join(rows)


我们来把他放在一个简单的分配了一些内存的应用里,然后调用


memory_summary:
"""
Don't forget to $ pip install pympler.
"""
import sys
from StringIO import StringIO

def memory_summary():
    # ... (see above)

# Allocate some memory
my_str = 'a' * 2**26
class MyObject(object):
    def __init__(self):
        self.memory = str(id(self)) * 2**10
my_objs = [MyObject() for _ in xrange(2**16)]

print(memory_summary())


运行这个例子将会得到像下面打印出的结果,这将会帮你看出应用中哪些对象在占用最多的内存



举个例子,我们看到str这个我们分配的对象占用了最大的内存,大约65MB.就像我们所期望的,有大约 2^16 = 65536个MyObject的实例,总共占用了4MB空间.

但是我们如何web应用产品中怎样读取这个信息呢?


我将 memory_summary()以HTTP basic auth加密并作为普通文本输出到/debug/memory.这样就可以在app运行时进入分配统计.

还有个更高级的方法追踪这些统计就是在 service like DataDog (https://dbader.org/blog/monitoring-your-nodejs-app-with-datadog)订阅他们,就可以实时绘制并追踪.然而,很多时候我们可以简单的解决这个问题,比如打印统计到应用的log里差不多就OK了.

请注意这些统计结果是per interpreter process(单解释器程序).如果你用多个CPython以负载均衡运行web应用程序,那么你就得搞清楚这些内存分析结果.

另外, 举个简单的例子,我发现那些占用最多内存的对象给我了关于内存用处模式的更多想法,并有助于减少后续工作所使用的内存消耗.


英文原文: https://dbader.org/blog/debugging-python-memory-usage
译者:panda