这周我们在工作中又遇到了一个小问题。我们用Python完成了一个转换脚本,正常情况下,程序完成转换仅需要几秒,但在某些情况下,程序完成转换的速度非常慢,大约需要几分钟。所以我们非常好奇,程序到底做了什么会变得如此之慢?
经过一番查阅,我们找到了一款性能分析工具:pyinstrument ,通过它我们就能很方便的找到程序执行过程中,不同函数及代码的执行时间,进而找到程序执行慢的原因并优化我们的程序。
接下来我们就来看看它的使用方法吧。
首先还是安装:
pip install pyinstrument
安装后,Pyinstrument的使用方法,分为两种,一种是在终端里运行 pyinstrument 命令加参数来实现,另一种是直接在代码中嵌入分析代码。
我们先介绍直接在代码中嵌入分析代码的方法,这种方法相对比较灵活,也较常用。
假设,我们编写了以下一段采集音频并收集其主要频率及音量的代码 Demo.py
timer = 10 #记录时间
thres = 100 #阈值,越大过滤的内容越多
#读取波形文件
freq, all_array = wavfile.read("1k.wav")
#分析波形文件,并得到其中的主要频率及最大、平均音量
final_freq_list , vol_list =get_freq_vol(all_array,freq,thres=100, range_thres=20)
如果我们想知道,这段代码中,各语句执行的时间,我们只需要在执行代码前实例化Profiler并启动,在代码执行结束后停止Profiler并打印分析结果。
#导入pyinstrument并实例化Profiler分析器
from pyinstrument import Profiler
profiler = Profiler()
profiler.start()
timer = 10 #记录时间
thres = 100 #阈值,越大过滤的内容越多
#读取波形文件
freq, all_array = wavfile.read("1k.wav")
#分析波形文件,并得到其中的主要频率及最大、平均音量
final_freq_list , vol_list =get_freq_vol(all_array,freq,thres=100, range_thres=20)
#结束Profiler,并输出分析结果
profiler.stop()
profiler.print()
执行这段代码后,程序会输出如下结果。

pyinstrument 的分析结果默认是按照代码执行的时间的快慢来排序的,依次是从慢到快,所以我们能很快定位到整个程序执行最慢的代码,是get_freq_vol中的fft函数。
由于fft是第三方库的内建函数,所以pyinstrument 默认会隐藏针对这个函数的细节,如果想查看细节的话,也可以在代码最后加入如下语句profiler.open_in_browser()
,这样程序运行结束后,pyinstrument 会输出结果到html中,并自动通过浏览器打开它。
在浏览器中,我们就可以展开并查看这些隐藏的细节了。

接着,简单介绍下终端运行的方法,我们可以直接在Dos窗口中通过pyinstrument [options] scriptfile [arg]的方式,让Pyinstrument对某个py文件进行性能分析并输出结果 ,
下面的命令,是让Pyinstrument对demo.py进行分析,并输出结果到HTML文件中:
pyinstrument --outfile=demo.html -r html demo.py
以下是pyinstrument 支持的命令行参数:
Usage: pyinstrument [options] scriptfile [arg] ...
Options:
--version show program's version number and exit
-h, --help show this help message and exit
--load-prev=ID Instead of running a script, load a previous report
-m MODULE_NAME run library module as a script, like 'python -m
module'
-o OUTFILE, --outfile=OUTFILE
save to <outfile>
-r RENDERER, --renderer=RENDERER
how the report should be rendered. One of: 'text',
'html', 'json', or python import path to a renderer
class
-t, --timeline render as a timeline - preserve ordering and don't
condense repeated calls
--hide=EXPR glob-style pattern matching the file paths whose
frames to hide. Defaults to '*/lib/*'.
--hide-regex=REGEX regex matching the file paths whose frames to hide.
Useful if --hide doesn't give enough control.
--show=EXPR glob-style pattern matching the file paths whose
frames to show, regardless of --hide or --hide-regex.
For example, use --show '*/<library>/*' to show frames
within a library that would otherwise be hidden.
--show-regex=REGEX regex matching the file paths whose frames to always
show. Useful if --show doesn't give enough control.
--show-all show everything
--unicode (text renderer only) force unicode text output
--no-unicode (text renderer only) force ascii text output
--color (text renderer only) force ansi color text output
--no-color (text renderer only) force no color text output
总结,在优化程序运行速度时, pyinstrument起到了重要的分析作用。我们只有先定位到程序执行慢的代码,才能找到其慢的原因,再根据原因来指定优化方案。
网友评论