《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性能分析工具的主要内容,如果未能解决你的问题,请参考以下文章

python爬虫开发之urllib模块详细使用方法与实例全解

python里面pip作用是啥?

Python3中urllib使用与源代码

8个无需编写代码即可使用Python内置库的方法

python爬虫---从零开始Urllib库

python_库学习_01