本地测试一发,确实能稳定复现…
无法判断框架还是自己写的Code 的问题。
开始搜索一些,比如这个 Python 内存泄漏调试指导思想 看来看去,这些文章大致分为两类,一部分是介绍 Python 垃圾回收机制;另一部分是介绍公众调试工具的使用。 有的文章里面还总结了常见的出现内存泄露的情景:
前两种情况,没什么好说的,对于第三种情况,这里补充一个例子
1 | a=[] |
Python中的对象主要分为类型对象和实例对象, 除了内置的类型对象外,都存在于堆上,内置的类型对象则静态分配内存. 为int分配的内存是永远也不会被python释放的,所有的int对象使用的内存大小和同时存在的int数量的最大值有关.str对象也存在同样的问题。
参考:
引用计数(主);
标记-清除(效率不高);
分代收集。
以下情况时,对象的引用计数增加:
以下情况时,对象的引用计数减少:
有 del() 函数的对象间的循环引用是导致内存泄漏的主凶。 另外需要说明:对没有 del() 函数的 Python 对象间的循环引用,是可以被自动垃圾回收掉的。
对于大的数组解决的方式,基本只有用yield来将列表对象转换为生成器对象。列表对象会同时生成所有元素,从而直接分配所有内存。而生成器则是一次生成一个元素,比较节约内存。
gc
内置模块, 函数少功能基本, 使用简单, 作为python开发者里边的内容必须过一遍个人最终使用感受:
上边这些虽然有用但是总是搞不到点子上, 而且都需要改我的源程序, 比较费劲, 线上的代码不是说改就能改的, 而且他们功能也都比较弱, 后来发现两个强大的工具:
开始的时候非常想用tracemalloc, 可是对python2特别不友好, 需要重新编译python, 而且只能用python2.7.8编译, 编译好了也不容易嵌入到虚拟环境中, 头大, 果断换第二个.
注: pyrasite使用之前需要在root用户下运行命令 echo 0 > /proc/sys/kernel/yama/ptrace_scope后才能正常使用
pyrasite里边有一个工具叫pyrasite-memory-viewer, 功能和guppy差不多, 不过可以对内存使用统计和对象之间的引用关系进行快照保存, 很易用也很强大。
使用各种工具和方法查内存使用情况和代码运行状态,直到查出问题所在。
查看 进程的线程数量
1 | ps -o nlwp <pid> |
根据对象的id/address动态获取对象
1 | import ctypes |
*查看垃圾回收的日志 *
1 | gc.set_debug(...) |