我知道python有自己的内存管理实现,使用不同大小和更多对象的areans,虽然我还没有找到完整的文档。 我仍然想了解幕后发生的事情。
后台是一个长期运行的python2数据库应用程序,它不知何故泄漏内存,它运行在64位Linux上。 每天这个应用程序都会读取数据库中的一些数据,它总计达到~3.5GB的RAM用量,只是为了读取行(使用MySQLdb)。大约有3.5M行,之后减少到几百行,剩下的就超出了范围(“释放”)。
但是python-2.7只释放了现在“未使用”内存的一小部分。我很害怕以后重用内存,但我观察到这种内存似乎“慢慢泄漏”。上面提到的数据库应用程序每天都会读取这一大块数据。连续读取两次(或多次)只为第一次读取分配内存,然后显然重用了这个内存。但让它运行几个小时,然后再次读取数据库数据会产生下一个3 + GB的内存分配峰值(再次永远不会被释放)。
要添加更多背景(并使事情更难解释),我必须说这个数据库应用程序不是空闲但是永久执行任务。我很确定通过监视内存使用情况(nagios性能数据),如果没有这个特定的数据库查询,内存使用量永远不会攀升到3.5GB RAM(甚至接近)。但启用此查询每天会增加3 + GB RAM。 有问题的查询主要返回唯一的整数和浮点数。
这是我开始怀疑python的主要原因。我觉得我已经阅读了大量的信息,看了_PyObject_DebugMallocStats(),但不知道python决定保留几千兆字节的原因(或原因)。
归结为一个非常简单的例子(不代表有关数据的真实情况,我知道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-heap但是到目前为止无法使用它。
我实际上不相信有解决方案(除了重新启动应用程序或减少从数据库读取的数据量)。但我真的很感激有关这一主题的任何见解。
编辑:
总结一下我的问题:为什么python-2.7会保留这个内存?
答案 0 :(得分:2)
range
示例保留了大量内存,因为Python 2.7永远不会释放int
s:
然而,这应该不是问题,除非在某些时候,几千兆字节的同时存在。否则,Python将使用旧的,丢弃的int来表示您使用的任何新的int。如果你做有几千兆字节的实时内容,我建议你找一种方法来保持较少的内容。