python的内存管理和垃圾回收机制,Python 内存溢出
Python内存泄漏和内存溢出的解决方案
发布时间:2020-10-30 23:08:34
来源:易俗云
阅读:92
作者:利亚
本文将详细解释Python内存泄漏和内存溢出的解决方案。文章内容质量很高,边肖分享给大家,供参考。希望你看完这篇文章能有所了解。
首先,内存泄漏
和Java程序一样,Python本身也有垃圾回收的功能,但是也造成了内存泄漏的问题。
对于一个用python实现的长时间运行的后台服务进程,如果内存一直增长,很可能存在“内存泄漏”。
1.内存泄漏的原因
对于python这种支持垃圾回收的语言来说,怎么还会有内存泄漏呢?总结起来有三个原因:C语言开发的底层模块发生了内存泄漏。
代码使用一个全局列表、dict或者其他容器,不停地在这些容器中插入对象,用完后忘记删除回收。
代码中存在“引用循环”,循环引用的对象定义了__del__方法,所以会出现内存泄漏。
为什么循环引用的对象定义了__del__方法后collect不起作用?
gc模块最常用的方法是gc.collect()方法,用来对循环引用的对象进行垃圾收集。
如果我们在类中重载__del__方法。__del__方法定义了用del语句删除对象时除释放内存空间以外的操作。
一般来说,在使用del语句时,解释器会首先查看要删除的对象的引用计数。如果为0,它将释放内存并执行del方法。
这里首先说明,del语句出现时,其引用计数不为0(因为循环引用的存在),所以解释器不释放内存;
再者,在执行collect方法时,要清除循环引用产生的无效引用计数,以达到del的目的。对于这两个圆形参照物,
Python无法判断调用他们的del方法时是否会用到对方对象。比如b._a,也就是A,在做b.del()的时候可能会用到。如果A在那之前已经发布了,那就完全GG了。
为了避免这种情况,collect方法在默认情况下不收集用del方法重载的循环引用对象,它们的状态将从不可到达变为不可收集。因为是不可收集的,自然不会被collect处理,所以进入了垃圾列表。
2.内存泄漏的诊断思路
无论是哪种内存泄露,最终的表现都是一些python对象在不断的增长;因此,首先要做的就是找到这些例外的对象。
3.诊断步骤
使用的工具:gc模块和objgraph模块
gc模块是Python的垃圾收集器模块,gc使用标签清除算法来收集垃圾。
Objgraph是一个诊断内存问题的工具。1.在维修程序的循环逻辑中,选择一个诊断点。
2.在诊断点,插入以下诊断语句
导入gc
导入对象图
# # #强制垃圾收集
gc.collect()
# # #打印出对象数量最多的50种信息。
obj graph . show _ most _ common _ types(限制=50)
4.检查统计信息以发现异常对象。
运行诊断语句的服务程序,并将屏幕上打印的统计数据重定向至日志。运行一段时间后,可以分析日志,看看哪些对象在不断增长。
例如,结果可能是:
多线程程序以多个线程作为生产者,一个线程作为消费者,通过向异步队列发送元组对象来进行通信。
因为消费者的处理速度跟不上生产者,没有同步,异步队列中的对象越来越多。
第二,内存溢出
1.内存溢出导致加载到内存中的数据量过大,比如一次从数据库中取出太多的数据。
集合中有对对象的引用,使用后没有清空,导致堆积,JVM无法回收。
代码中存在无限循环,或者循环导致的重复对象实体太多。
使用第三方软件中的错误
启动参数记忆值设置太小。
2.内存溢出的解决方案
第一步是修改JVM启动参数,直接增加内存(-Xms,-Xmx参数一定不能忘记)
其次,检查错误日志,查看在“OutOfMemory”错误之前是否有其他异常或错误。
第三步是遍历并分析代码,找出可能发生内存溢出的地方。
重点关注以下几点:检查是否存在获取数据库查询中所有数据的查询。一般来说,如果一次取100,000条记录到内存中,可能会导致内存溢出。这个问题是隐藏的。在上线之前,数据库里的数据比较少,不容易出问题。上线后数据库中数据较多,一次查询就可能造成内存溢出。因此,数据库查询应该尽可能分页。
检查代码中是否有无限循环或递归调用。
检查是否存在重复生成新对象实体的大循环。
检查列表、地图等集合对象使用后是否未清除。像List和MAP这样的集合对象总是有对对象的引用,所以这些对象不能被GC回收。
步骤4:使用内存查看工具动态查看内存使用情况。
第三,内存泄漏和内存溢出的区别
内存溢出是指当JVM中没有足够的可用内存来申请内存空间时,会抛出OOM,即内存溢出。
内存泄漏是指一个内存空间被应用于JVM,但在使用后没有被释放。因为没有释放,所以加载时这个内存区域的其他类不能应用。
同时,当前类没有这个内存空间的内存地址,无法使用,相当于丢失了一个内存,这就是内存泄漏。
值得注意的是,内存泄漏最终会导致内存溢出。很容易理解大量记忆丢失。最后当然是内存不够了。
以上就是Python对内存泄漏和内存溢出的解决方案。希望以上能对你有所帮助,你能学到更多的知识。如果你觉得文章不错,可以分享给更多人看。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。