# 内存泄漏问题排查思路
# 内存泄漏问题排查思路
对于Python进程内存泄漏问题定位,可以按如下步骤进行:
- 先确认下内存中一直保持增长的是什么类型对象
- 看看内存分配最频繁的地方是哪里
- 将这类占内存比较多的对象打印出来进行分析,看看是否有业务上信息
- 将重点怀疑的对象通过objgraph打印出引用关系从而分析出内存泄漏的问题源自哪里
# 可能产生内存泄漏问题的场景
业务代码BUG
- 代码中创建大量对象,虽然这些对象不再被访问,但是由于它们仍然被一些全局对象引用,GC无法释放这些对象。
- 容器无限制添加元素-list等一直append
未正确关闭文件句柄: Python中的文件对象是与操作系统文件句柄相关联,如果文件对象没有被正确关闭,操作系统文件句柄无法释放,导致内存泄漏。
为正确释放C扩展模块或外部库中的内存: 应用使用了C扩展模块或者外部库来扩展Python功能,如果其中存在内存泄漏则上层应用运行时也会内存泄漏。
循环引用: Python 的垃圾回收机制是基于引用计数的,当一个对象的引用计数为 0 时,垃圾回收机制会自动回收这个对象。如果存在循环引用,即两个或多个对象相互引用,导致它们的引用数不会变为 0,垃圾回收机制无法回收这些对象,从而导致内存泄漏。
存疑,python有标记清除算法来避免循环引用,一般不会出现这个问题。标记清除法、 标记清除算法
# 排查工具
# Objgraph
这是一个可以用来查看对象间引用关系的工具,比如对于一些大对象总是不释放的问题,可以通过这个工具分析出其到底是被哪些对象所引用。
# 工具安装
pip install objgraph // 安装objgraph
pip install xdot // 安装可视化依赖库
pip install graphviz // 安装绘图依赖库
apt-get install graphviz // 安装绘图工具
# 使用介绍
上面代码构造了一个循环引用的场景,通过objgrap可以看到对象引用关系图如下:
注意:此工具在生成对象间引用关系时是一个比较耗时的操作,需要确保执行频率不要太高以免影响业务代码流程,而且我们也没必要每次都要将内存中所有对象引用关系都搞出来,这样不仅耗时而且也难以分析。
# pympler
此工具可以方便获取到当前内存使用情况,比如过去占用内存最多的前十个对象类型,对象个数以及占用内存字节。
# 工具安装
pip install pympler
# 使用介绍
上述代码构造了一个字符串和一个字典,通过pympler可以看到str和dict类型在内存中数据量。
# tracemalloc
tracemalloc是一个用于跟踪Python应用内存分配的工具,在python3.4以上此工具为标准库,所以无需安装。
# 使用介绍
我们可以看到tracemalloc不仅可以获取占内存最多的对象,同时也能看到改对象创建的堆栈。