首页
技术小册
AIGC
面试刷题
技术文章
MAGENTO
云计算
视频课程
源码下载
PDF书籍
「涨薪秘籍」
登录
注册
代码优化篇-循环优化
数学计算优化
降低垃圾回收的频率
调整垃圾回收参数
Python Profile简介
使用Profile分析Python代码
GUI图形界面生成性能报告
Python架构模型简介
基于Python的C拓展组件的优化思路
代码瓶颈的产生
代码执行速度的恢复
基于Django邮件发送
基于FastAPI邮件发送
基于Django高并发邮件发送
基于FastAPI高并发邮件发送
Locust框架邮件发送并发性能测试
基于Django打印日志
基于FastAPI打印日志
基于Django高并发打印日志
基于FastAPI高并发打印日志
Locust框架日志打印并发性能测试
基于Django的用户登录注册功能
基于FastAPI用户登录注册
基于Django高并发环境登录注册
基于FastAPI高并发环境登录注册
Locust框架用户注册登录并发性能测试
高并发项目常用应对方案
Python项目高性能优化方案
当前位置:
首页>>
技术小册>>
Python高性能编程与实战
小册名称:Python高性能编程与实战
对于CPython解释器或虚拟机来说,最常用也是最简单的垃圾回收优化手段就是降低垃圾回收的频率。Python中降低垃圾回收频率的手段一般有两种:第一种是引入Python中的gc包,另一种是结合Python中的垃圾回收算法。 gc包是CPython官方为Python开发者提供的一个资源包。该包中包含对Python中的垃圾进行回收的基础操作方法。开发者可以结合这些基础操作方法,手动设置Python垃圾回收的时机。Python中垃圾回收的基础操作方法共有4个,分别是disable()、collect()、set_threshold ()、set_debug ()。这四种基础操作方法分别用于暂停自动垃圾回收、返回垃圾回收机制所找到无法到达的对象的数量、设置Python垃圾回收的阈值、设置垃圾回收的调试标记并将调试信息写入std.err()方法。对于上述基础操作方法的使用,笔者写了几个示例代码,具体如下: ![](/uploads/images/20231206/8a32ee0833d8e097d3ee1f991c64ca0e.png) 我们知道,Python中常用的垃圾回收算法是引用计数算法。引用计数算法是一种非常高效的内存管理手段,当Python对象被调用时,其引用计数器的值就增加1;当Python对象不再被调用时,其引用计数器的值就会减1,直到减到0为止。当Python中一个对象的引用计数器的值等于0时,该对象就会被删除。 上述代码的执行结果如图13-5所示。 gc.disable()方法用于暂停自动垃圾回收。当自动的垃圾回收机制暂停时,Python对象的引用计数器值也就不再由CPython解释器或虚拟机进行自动管理,而是交由开发者手动进行干预。在上述代码中,笔者使用了objgraph第三方工具包来查看a、b两个对象引用计数器的值。通过打印结果可以发现,这两个对象的引用计数器的值均为0,那么当不再调用gc.disable()方法时,a、b两个对象就会被回收,以此来实现降低垃圾回收的频率。 ![](/uploads/images/20231206/2c5444517a77a5545be9fc1c7db1f39b.png) 开发者需要对gc.disable()方法进行灵活应用,在确实需要暂停自动垃圾回收的地方大胆使用,在那些确实不需要暂停自动垃圾回收的地方就一定不能使用,切记不能为了Python代码的执行速度而随意滥用该方法。 当开发者在编写Python代码时,切记不要编写重复引用或循环引用的Python代码,如果在不经意间编写了循环引用的代码,那么在进行代码审查时,一定要对其进行优化,因为这种代码不会被Python中的垃圾回收机制回收。笔者编写了一个简单的循环引用代码: ![](/uploads/images/20231206/c004d13e99ad1d2272a48ae7e7069931.png) 在调用上述代码中的test3()方法时就会发生对象a和对象b循环引用的情况,导致垃圾回收机制一直不能对上述代码进行回收,因为上述代码执行完毕时,对象a和对象b的引用计数器的值均为1,如图13-6所示。 ![](/uploads/images/20231206/a1608f9932ef8eda273cc85af31befc1.png) 如果开发者不将该循环引用进行优化,上述代码所占用的内存空间将会越来越大。结束上述代码的循环引用其实很简单,只需要在test3()方法中调用相对应的destroy()方法即可,代码如下所示: ![](/uploads/images/20231206/03b07cc850d4d37fa448a85687cb7042.png) 在test3()方法中,笔者分别调用了对象a和对象b的destroy()方法,来手动结束这一循环引用。在调用了对象a和对象b的destroy()方法之后,对象a和对象b的引用计数器的值变为0,如图13-7所示。 ![](/uploads/images/20231206/5147b5d47fa513b789aba35b540ea9ed.png) 这样,Python中的垃圾回收机制就可以回收掉上述代码了(详见上述回收过程)。位于test3()方法中的destroy()方法只是笔者用于演示手动终止循环引用的标记方法,并不代表Python中所有的循环引用都需要通过这种方法进行终止,而是应该根据实际的项目环境和代码环境,来编写具体Python项目的循环引用终止条件,这样才能降低垃圾回收的频率。 当我们通过上述手段降低了垃圾回收频率之后,Python项目在运行时就不会有明显的卡顿,对于CPython的内存占用来说,虽说占用了一些内存空间,但是项目整体的运行效率会得到提升。这是一种以空间换取时间的优化方式。
上一篇:
数学计算优化
下一篇:
调整垃圾回收参数
该分类下的相关小册推荐:
Python机器学习实战
Python编程轻松进阶(五)
Python合辑7-集合、列表与元组
Python合辑12-面向对象
Python合辑9-判断和循环
Python编程轻松进阶(三)
Python合辑5-格式化字符串
剑指Python(磨刀不误砍柴工)
剑指Python(万变不离其宗)
Python爬虫入门与实战开发(下)
Python编程轻松进阶(四)
Python合辑11-闭包函数