《Python开发 - Python库》Python性能分析工具
Posted Bruceoxl
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《Python开发 - Python库》Python性能分析工具相关的知识,希望对你有一定的参考价值。
我们在写完代码后,一般需要对代码进行优化,而代码优化的前提是需要了解性能瓶颈在什么地方,程序运行的主要时间是消耗在哪里,对于比较复杂的代码可以借助一些工具来定位,python 内置了丰富的性能分析工具,如 profile与 hotshot 等。其中 profiler 是 python 自带的一组程序,能够描述程序运行时候的性能,并提供各种统计帮助用户定位程序的性能瓶颈。
对于Python,比较常用的Profile工具有三个:
- profile 纯python语言实现,返回函数整体损耗。(自带)
- cProfile 同profile,部分实现native化,返回函数整体损耗。(自带)
- line_profile 返回函数每行损耗。(第三方)
cProfile 和 profile 提供了 Python 程序的确定性性能分析。profile 是一组统计数据,描述程序的各个部分执行的频率和时间。这些统计数据可以通过 pstats 模块格式化为报表。
Python 标准库提供了同一分析接口的两种不同实现:
1.对于大多数用户,建议使用 cProfile ;这是一个 C 扩展插件,因为其合理的运行开销,所以适合于分析长时间运行的程序。该插件基于 lsprof ,由 Brett Rosen 和 Ted Chaotter 贡献。
2.profile 是一个纯 Python 模块(cProfile 就是模拟其接口的 C 语言实现),但它会显著增加配置程序的开销。如果你正在尝试以某种方式扩展分析器,则使用此模块可能会更容易完成任务。该模块最初由 Jim Roskind 设计和编写。
【注】profiler 分析器模块被设计为给指定的程序提供执行概要文件,而不是用于基准测试目的( timeit 才是用于此目标的,它能获得合理准确的结果)。这特别适用于将 Python 代码与 C 代码进行基准测试:分析器为Python 代码引入开销,但不会为 C级别的函数引入开销,因此 C 代码似乎比任何Python 代码都更快。
笔者本文将介绍cProfile 和 profile来对Python代码进行性能/耗时分析。
1 cProfile性能/耗时分析工具
cProfile是基于lsprof的用C语言实现的扩展应用,运行开销比较合理,适合分析运行时间较长的程序,推荐使用这个模块。
cProfile模块都是本身集成在Python源代码中,所以不用特意安装,适合在权限不够的服务器上测试代码性能,使用时直接 import 就行。
1.代码方式
cProfile 是 Python 默认的性能分析器,选它没错的。可以在 python 脚本里运行,例如:
def main():
.....
if __name__ == "__main__":
import cProfile
# 注意:运行的函数名要使用字符串的形式且带括号
# 直接把分析结果打印到控制台
cProfile.run('main()')
# 把分析结果保存到文件中
cProfile.run("main()", filename="result.out")
# 增加排序方式
cProfile.run("main()", filename="result.out", sort="cumulative")
运行结果类似下图:
显示结果列含义如下:
列名 | 含义 |
---|---|
ncalls | 表示函数调用的次数 |
tottime | 表示指定函数的总的运行时间,除掉函数中调用子函数的运行时间 |
percall | (第一个percall)等于 tottime/ncalls |
cumtime | 表示该函数及其所有子函数的调用运行的时间,即函数开始调用到返回的时间 |
percall | (第二个percall)即函数运行一次的平均时间,等于 cumtime/ncalls |
filename:lineno(function) | 每个函数调用的具体信息,一般指向函数名 |
2.命令方式
#运行命令查看性能分析结果:
python -m cProfile main.py
#将性能分析结果保存到result文件
python -m cProfile -o result.out main.py
#增加排序方式
python -m cProfile -o result.out -s cumulative main.py
【注】-m 表示执行 cProfile 模块, -s cumulative 表示对每个函数累计花费时间进行排序,可以让我们很直观的看到哪一部分的代码执行的最慢。
结果和使用代码的方式相同,还有一个好处是不用修改源码,只需简单加几个参数即可。
2 profile性能/耗时分析工具
profile 和cProfile一样,的使用非常简单,只需要在使用之前进行 import 即可,也可以在命令行中使用。
1.代码方式
def main():
.....
if __name__ == "__main__":
import profile
# 注意:运行的函数名要使用字符串的形式且带括号
# 直接把分析结果打印到控制台
profile.run('main()')
# 把分析结果保存到文件中
profile.run("main()", filename="result.out")
# 增加排序方式
profile.run("main()", filename="result.out", sort="cumulative")
2.命令方式
#运行命令查看性能分析结果
python -m profile main.py
#将性能分析结果保存到result文件
python -m profile -o result.out main.py
#增加排序方式
python -m profile -o result.out -s cumulative main.py
以上两种方式的运行结果和也cProfile也是一样的。
3 pstats表格化分析原始文件
Profile 生成的原始文件并不易读,需要借助其他工具来处理原始文件。pstats 模块可以以表格化的方式来处理 cProfile 生成的原始文件。
1.代码方式
import pstats
# 创建 Stats 对象
p = pstats.Stats('result.out')
# 按照运行时间和函数名进行排序
# p.strip_dirs().sort_stats("cumulative", "name").print_stats(0.5)
p.strip_dirs().sort_stats("cumulative", "name").print_stats(30)
# 按照函数名排序,只打印前 3 行函数的信息, 参数还可为小数, 表示前百分之几的函数信息
# 如果想知道有哪些函数调用了 ccc
# p.print_callers(0.5, "fun")
# 查看 ccc() 函数中调用了哪些函数
# p.print_callees("fun")
2.命令方式
#正常输出
python -c “import pstats; p=pstats.Stats('reslut.out); p.print_stats()”
#时间排序查看
python -c "import pstats; p=pstats.Stats(‘result.out’); p.sort_stats(‘time’).print_stats()
sort_stats支持的参数:calls, cumulative, file, line, module, name, nfl, pcalls, stdname, time
结果还是可前面的一致。
4 snakeviz图形化分析原始文件
虽然Profile的输出已经比较直观,但通过终端来分析,总是不太好看,接下来使用图形化工具从不同维度进行分析,更快地找出瓶颈代码。Profile图形化工具有VisualPyTune、QCacheGrind、RunSnakeRun等,但是我最推荐是snakeviz。
Snakeviz只需要简单安装就能使用,通过开启一个WEB服务,就可通过浏览器查看Python软件的性能。
1.安装
#pip install snakeviz
2.使用
#snakeviz result.out
然后就会在弹出一个 snakeviz 的本地网页,可以在网页上自由点击查看哪个代码最耗时,非常直观方便。
欢迎访问我的网站:
BruceOu的哔哩哔哩
BruceOu的主页
BruceOu的博客
BruceOu的CSDN博客
接收更多精彩文章及资源推送,请订阅我的微信公众号:
以上是关于《Python开发 - Python库》Python性能分析工具的主要内容,如果未能解决你的问题,请参考以下文章