我知道python有自己的内存管理实现,使用arean来处理不同大小的对象,甚至更多,尽管我还没有找到一个完整的文档。
不过,我还是想知道在幕后发生了什么。在
后台是一个长时间运行的python2数据库应用程序,它似乎在泄漏内存,它运行在64位linux上。
这个应用程序每天都会从数据库中读取一些数据,仅用于读取行(使用MySQLdb)的RAM使用量总计约为3.5GB。剩下的几行被释放到100.5米的范围内(“剩下的几行被缩小为3行”)。在
但是python-2.7只释放了现在“未使用”内存的一小部分。我知道这些记忆以后会被重用,但我观察到,不知怎么的,这些记忆似乎在“慢慢地泄漏”。上面提到的数据库应用程序每天都要读取大量数据。连续读取两次(或多次)只会为第一次读取分配内存,然后显然会重用此内存。但是让它运行几个小时,然后再次读取DB数据,就会产生下一个3+GB的内存分配峰值(这一峰值永远不会被释放)。在
为了添加更多的背景(让事情变得更糟),我不得不说这个数据库应用程序不是空闲的,而是永久性地执行任务。通过监视内存使用情况(nagios性能数据),我非常肯定,如果没有这个特定的DB查询,内存使用率永远不会攀升到3.5GB RAM(甚至接近)。但启用了GB+3,则每天都会添加此查询。
所讨论的查询返回的大多是唯一的整数和浮点数。在
这就是我开始怀疑python的主要原因。我觉得我已经阅读了大量的信息,查看了_PyObject_DebugMallocStats(),但不知道python决定保留几GB的内容(或原因)。在
它可以归结为一个非常简单的例子(不代表数据的真实情况,我知道xrange()):def mem_usage(pid=None):
mem = 0
proc = str(pid or "self")
with open("/proc/%s/smaps" % proc) as fstat:
for l in fstat:
if not l.startswith("Private_"):
continue
mem += int(l.split(":", 1)[1].strip().split(" ", 1)[0])
return mem
mem_usage() # reports a few MB
x = list(range(100000000)) # use list() for py3k
mem_usage() # reports ~3GB
del x
mem_usage() # reports ~2.5GB
有趣的是,当我删除大列表时,py3k会释放内存。不仅是一小部分,而且几乎所有的内存使用量只比开始时略高。在
我用memory_profiler(我想它不会比给定的mem_usage()函数做得更多)进行了研究,但没有任何见解。我读过关于gdb堆的文章,但是到目前为止还不能让它工作。在
我实际上不相信有解决方案(除了重新启动应用程序或减少从数据库读取的数据量)。但我真的很感激你对这个话题的任何见解。在
编辑:
总结一下我的问题:python-2.7为什么要保持这个内存的分配?在