Python 优化第一步: 性能分析实践 使用cporfile+gprof2dot可视化
拿来主义:
1 2 | python - m cProfile - o profile.pstats to_profile.py gprof2dot - f pstats profile.pstats |dot - Tpng - o click.png |
然后顺着浅色线条优化就OK了。
windows下:
google下graphviz-2.38.msi,然后安装。dot命令需要。
git clone https://github.com/jrfonseca/gprof2dot.git。
然后就是:
1 2 | D:\KwDownload\gprof2dot - master\gprof2dot - master>python gprof2dot.py - f pstats C:\Users\l00379637\AppData\Roaming\eSpace_Desktop\UserData\l00379637\ReceiveFile\profile.pstats | "c:\Program Files (x86)\Graphviz2.38\bin\dot.exe" - Tpng - o cli ck.png |
Python 优化第一步: 性能分析实践
Python的性能分析器
Python中最常用的性能分析工具主要有:cProfiler, line_profiler以及memory_profiler等。他们以不同的方式帮助我们分析Python代码的性能。我们这里主要关注Python内置的cProfiler,并使用它帮助我们分析并优化程序。
cProfiler
快速使用
这里我先拿上官方文档的一个简单例子来对cProfiler的简单使用进行简单介绍。
1
2
3
|
import cProfile
import re
cProfile.run('re.compile("foo|bar")')
|
分析结果:
1
2
3
4
5
6
7
8
9
10
|
197 function calls (192 primitive calls) in 0.002 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.001 0.001 <string>:1(<module>)
1 0.000 0.000 0.001 0.001 re.py:212(compile)
1 0.000 0.000 0.001 0.001 re.py:268(_compile)
1 0.000 0.000 0.000 0.000 sre_compile.py:172(_compile_charset)
1 0.000 0.000 0.000 0.000 sre_compile.py:201(_optimize_charset)
4 0.000 0.000 0.000 0.000 sre_compile.py:25(_identityfunction)
3/1 0.000 0.000 0.000 0.000 sre_compile.py:33(_compile)
|
从分析报告结果中我们可以得到很多信息:
- 整个过程一共有197个函数调用被监控,其中192个是原生调用(即不涉及递归调用)
- 总共执行的时间为0.002秒
- 结果列表中是按照标准名称进行排序,也就是按照字符串的打印方式(数字也当作字符串)
- 在列表中:
ncalls
表示函数调用的次数(有两个数值表示有递归调用,总调用次数/原生调用次数)tottime
是函数内部调用时间(不包括他自己调用的其他函数的时间)percall
等于tottime
/ncalls
cumtime
累积调用时间,与tottime相反,它包含了自己内部调用函数的时间- 最后一列,文件名,行号,函数名
优雅的使用
Python给我们提供了很多接口方便我们能够灵活的进行性能分析,其中主要包含两个类cProfile模块的Profile
类和pstat模块的Stats
类。
我们可以通过这两个类来将代码分析的功能进行封装以便在项目的其他地方能够灵活重复的使用进行分析。
这里还是需要对Profile
以及Stats
的几个常用接口进行简单总结:
Profile
类:
enable()
: 开始收集性能分析数据disable()
: 停止收集性能分析数据create_stats()
: 停止收集分析数据,并为已收集的数据创建stats
对象print_stats()
: 创建stats对象并打印分析结果dump_stats(filename)
: 把当前性能分析的结果写入文件(二进制格式)runcall(func, *args, **kwargs)
: 收集被调用函数func
的性能分析数据Stats
类
pstats模块提供的Stats
类可以帮助我们读取和操作stats文件(二进制格式)
1
2
|
import pstats
p = pstats.Stats('stats.prof')
|
Stats
类可以接受stats文件名,也可以直接接受cProfile.Profile
对象作为数据源。strip_dirs()
: 删除报告中所有函数文件名的路径信息dump_stats(filename)
: 把stats中的分析数据写入文件(效果同cProfile.Profile.dump_stats()
)sort_stats(*keys)
: 对报告列表进行排序,函数会依次按照传入的参数排序,关键词包括calls
,cumtime
等,具体参数参见https://docs.python.org/2/library/profile.html#pstats.Stats.sort_statsreverse_order()
: 逆反当前的排序print_stats(*restrictions)
: 把信息打印到标准输出。*restrictions
用于控制打印结果的形式, 例如(10, 1.0, ".*.py.*")
表示打印所有py文件的信息的前10行结果。
分析数据可视化
gprof2dot
Gprof2Dot可将多种Profiler的数据转成Graphviz可处理的图像表述。配合dot命令,即可得到不同函数所消耗的时间分析图。具体使用方法详见: https://github.com/jrfonseca/gprof2dot
因此我们可以利用它来为我们的程序生成分析图:
1
|
gprof2dot -f pstats mkm_run.prof | dot -Tpng -o mkm_run.png
|
于是我们路径下面就生成了mkm_run.png
我倒是蛮喜欢这个时间分析图,顺着浅色方格的看下去很容易发现程序的瓶颈部分,
每个node的信息如下:
1
2
3
4
5
|
+------------------------------+
| function name |
| total time % ( self time % ) |
| total calls |
+------------------------------+
|
每个edge的信息如下:
1
2
3
|
total time %
calls
parent --------------------> children
|
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」