gpt4 book ai didi

python - 是python2不愿意释放内存吗?

转载 作者:太空狗 更新时间:2023-10-29 11:14:38 25 4
gpt4 key购买 nike

我知道 python 有自己的内存管理实现,它使用区域来处理不同大小的对象等等,尽管我还没有找到详尽的文档。我仍然想了解幕后发生的事情。

背景是一个长时间运行的 python2 数据库应用程序,不知何故出现内存泄漏,它运行在 64 位 linux 上。每天这个应用程序都会从​​数据库中读取一些数据,它总计使用 ~3.5GB RAM 仅用于读取行(使用 MySQLdb)。大约有 350 万行,之后减少到几百行,其余行超出范围(“释放”)。

但是 python-2.7 只释放了现在“未使用”内存的一小部分。我知道内存稍后会被重用,但我观察到该内存似乎以某种方式“缓慢泄漏”。提到的数据库应用程序每天都会读取这一巨大的数据 block 。连续读取两次(或更多次)只会为第一次读取分配内存,然后显然会重用该内存。但是让它运行几个小时,然后再次读取数据库数据会产生下一个 3+GB 的内存分配峰值(它再也不会被释放)。

要添加更多背景知识(并使事情更难解释),我不得不说这个数据库应用程序不是空闲的,而是永久地执行任务。通过监控内存使用情况(nagios 性能数据),我非常确定如果没有这个特定的数据库查询,内存使用量永远不会攀升到 3.5GB RAM(甚至接近)。但是启用此查询每天会增加 3+GB RAM。有问题的查询主要返回唯一的整数和 float 。

这就是我开始怀疑 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 会保留分配的内存?

最佳答案

range 示例保留了大量内存,因为 Python 2.7 从不释放 int:

block_list is a singly-linked list of all PyIntBlocks ever allocated, linked via their next members. PyIntBlocks are never returned to the system before shutdown (PyInt_Fini).

然而,这应该不是问题,除非在某个时刻,几千兆字节的整数同时存在。否则,Python 将使用旧的、废弃的整数来表示您使用的任何新整数。如果您确实有几千兆字节的实时整数,我建议找到一种方法来一次保留更少的整数。

关于python - 是python2不愿意释放内存吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20632066/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com